I'm developing a "chat" app that retrieves some data (the messages) from a database (firebase real-time database), does some manipulations and then populates a listview in order to display them on the screen. I have 2 types of messages:
The first type is text messages, the manipulations on them are very short and don't take a long.
The second type is pictures. The manipulations on them are longer than on text (few seconds).
When the activity starts, the app retrieves all the messages from the database, and has to do the manipulations on each one of them (text and pictures). Before we see anything on the screen, it has to finish the manipulations on all the messages and then it takes a lot of time.
My question is: is there a way to populate each item in a different thread? Like to see on the screen the text messages appear (because the manipulations on them are fast) and then the pictures when each one of them finish at its own time (same idea like a website when we see the text before all the pictures finish to be loaded). Of course the messages need to appear in the same order like they were in the database (actually I retrieve them with the onChildAdded() function).
I really hope it was clear, and if not I will be happy to clarify any point.
Thanks everyone!!!
Define them as different Threads:
[...]recive messages
if (/*message an image?*/) {
new Thread(() -> {
//Do something
}).start();
} else {
new Thread(() -> {
//Do something else
}).start();
}
Related
I'm reading Sensor Data from Device Sensors(Multiple Sensors) and call a Method to show the data I received from sensors to the designed TextView.
The method I'm calling to update TextView:
private void UpdateDataStream(String _Entry,Boolean isAppend)
{
if(isAppend)
ViewHolder.append("\n("+sensorName+")"+_Entry);
else
ViewHolder.setText("("+sensorName+")"+_Entry);
}
Method called from SensorEventListener's , onSensorChanged Event.
What I couldn't figure out is how to prevent freeze while updating TextView; since sensor data update is intensive(considering it is from multiple sensors simultaneously) updating TextView cause Application to freeze or crash. I don't need to "print" every data I received, like It is enough for me to print for every 1-2 second, lost data can be ignored.
Is there any approach/patern or built-in structure to achieve this ?
(I'm new to programming in Java&Android, yet I'm familiar with multiprogramming, parallel programming concepts, yet I couldn't figure out how to apply them in this environment)
This is fastest solution:
https://github.com/ReactiveX/RxJava
http://reactivex.io/documentation/operators/debounce.html
Or you can:
create stack (for example)
write sensors data stream to stack from thread#1
in another infinite loop thread#2 read last data from stack every N time (don't forget to synchronize them)
clean the stack
write last data to TextView (don't forget to set text in ui thread: textView.post( () -> textView.setText("safe call") );
This relates to this Java question.
Here's my problem. I've written an app that allows people to do a lot of data entry, typing into a lot of separate fields. To confirm the change in each field they can often hit Return (for a single line field) or control-S (for multi-line fields where Return would be valid input), but that's cumbersome, so I also allowed fields to save their content when they lose focus. So users can type-tab-type and it all goes smoothly.
Except if they change a field and then click on the application window exit X in the corner. They expect that this counts as losing focus and will save that last change. But the lost focus event doesn't happen and the change is lost.
I could add a Done button, which would have the side effect of moving focus and saving the last field, and then exiting. But I shouldn't have to. There's a X in the corner and it should do the right thing.
My first thought was
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(.....
because I thought from there I could publish() something to my SwingWorker to tell it call loseFocus on everything. No such luck; publish() is protected.
Basically I need to do one last operation on my various widgets when X is clicked. How do I?
Edit: I should note that each editable widget (dropdown, JTextPane, etc) has been extended to hold the actual relevant data. All the data for that widget, e.g. whether the value the user typed is valid, what it was before he edited it, etc. is in those extended class instances. There's no other place values are held; this isn't model-view-controller.
The reason for this is that widgets can get changed either by user actions or network messages; a message can come in that throws out an existing widget entirely and replaces it with one with new content. In other words, doInBackground is in a permanent read-loop, reading network update messages and publish()ing those update requests to process(). User action happens as usual, between calls to process().
Bottom line,there's no global data structure to go to at exit time to get values. They're all in dozens to hundreds of data structures managed by the swing worker thread.The app itself, outside that swing worker thread, doesn't even know what sort of values and widgets exist - all widgets are created, placed and destroyed by network messages from the server. The rest of the app (what little there is) couldn't safely get to the data if it wanted to, unless I implemented a whole lot of shared data and locking.
It all works flawlessly, and I'd rather not redesign it all for this one tiny shutdown case. It just never occurred to me that I couldn't publish an extra "shut down" message into the work queue for process() from outside that thread. (I mean thread safe queues are trivial to implement; why didn't they?)
If the answer is "you can't talk to swing at shut down", I'll live with it. I do have a potentially evil workaround - I could have x do nothing but send a message to the server, which could write back a "you should shut down message" which could do the rest. But that seems ungainly.
The short answer is, there isn't a good solution. I tried installing a shutdown hook and publishing a message to the swing thread to tell it to finish up, and then gave the shutdown thread a 500ms sleep to give process() time to happen. process() wasn't called. publish() alone apparently isn't enough, once shutdown starts.
Bottom line, don't put data you need to get at in swing threads. Global data and synchronized functions is the only way to go.
Hey guys:) I'm currently working on an android project, where I want to realize a chat function. I know there are several tutorials which describe a chat app but I want to do it myself with my own Server.
In my MainActivity I start a self written updater in a new thread (bc. of network-operations can only be done outside the UI thread), which permanently checks, if the chat-protocol, which is stored on my server (RaspberryPi), has new messages from other users. If there are new messages, the Updater downloads it and stores it in a string. This works fine!
Now, when the updater receives a new message, I want to update the ListView in my Chat-Activity with the new message. This process should work at any time and update my ListView permanently (not with a refresh button or sth. like that).
My question is: how do i realize this the smoothest way - a strategy, not necessarily code. One idea, which works but feels a bit random, is to write the received messages in a shared preferences-file and load it in the chat-acivity via an infinite loop in the chat activity.
Is there a possibility to write the received messages directly in the ListView at any time from the thread with the updater which was startet in the MainActivity.
If needed i could upload the current code but i want to do it directly and not with an infinite loop.
Thanks for reading and maybe even for the help :)
You may want to save the received messages in SQLite database, and inside the activity, you can poll the database (suppose for every 5 seconds) and stop polling after the activity is destroyed.
Another way would be to use the static references of the views and update them from a different class. Even you are trying to update them from inside a background thread, you can update the UI using view.post()
SomeActivity.textView.post(new Runnable(){
#Override
public void run(){
SomeActivity.textView.setText("sth");
}
});
For my app, I have about 15Mb (which can be compressed with some processing power to about 5Mb) of audio+video+image data that I need to save to disk. For instance, I need to save this when user is interrupted with a phone call (because the activity might get killed after this) and when the user leaves the app.
I can save the data to SD card in about 10 seconds if I don't compress it and something like 20 seconds if I do compress it, where I'd like it compressed. What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
From some basic experiments, my activity gets killed if onPause hasn't finished after 5 seconds. Some ideas I've had:
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
(Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations). Even if I stored the original data and a list of the actions performed to recreate the data, the user would have to wait a minute or two when the app is next started up to process this.)
What options to I have for saving my data when onPause is called such that I can be sure the data has been saved?
Technically, what you want is impossible. There are no guarantees after onPause().
The best answer is what #Viktor Lannér suggested. To phrase it another way, don't wait until onPause() to need to do 10-20 seconds of I/O. Devise some mechanism to allow you to save incrementally as the user performs operations, as a fallback mechanism if nothing else. This is akin to how a database maintains a transaction log.
Starting a new Thread in onPause and saving the data there. This seems to work fine but seems like something I shouldn't be doing.
This is dangerous, because if the activity is closing (e.g., onDestroy() will be called momentarily), Android might terminate your process before your thread is completed.
Starting a service, copying the data to the service somehow (would this be slow?) and then getting the service to save the data. I think this puts a notification icon at the top of the phone, but I don't think it's awful for a user to see the "Saving data..." task here.
Make this be an IntentService, so it automatically shuts down when the work is complete. I wouldn't "copy the data to the service", but rather make the data centrally available, by a static data member if needed. This will not automatically put "a notification icon at the top of the phone", and for something of this duration, that is probably not needed.
Can I put the data in a SQL database quickly and then save it later when the user returns to the app?
Flash I/O is not faster for a SQL database than for anything else.
Due to the nature of the app, there really isn't any practical way I can save the data as I go because the user can transform the data in destructive ways with time consuming operations (e.g. 10 seconds for some operations
Then this probably isn't designed for a mobile platform. Consider whether this app is an appropriate use of the technology.
This application I've been working on has databases with multiple megabytes of data to sift through. A lot of the activities are just ListViews descending through various levels of data within the databases until we reach "documents", which is just HTML to be pulled from the DB(s) and displayed on the phone. The issue I am having is that some of these activities need to have the ability to search through the databases by capturing keystrokes and re-running the query with a "like %blah%" in it. This works reasonably quickly except when the user is first loading the data and when the user first enters a keystroke. I am using a ResourceCursorAdapter and I am generating the cursor in a background thread, but in order to do a listAdapter.changeCursor(), I have to use a Handler to post it to the main UI thread. This particular call is then freezing the UI thread just long enough to bring up the dreaded ANR dialog. I'm curious how I can offload this to a background thread totally so the user interface remains responsive and we don't have ANR dialogs popping up.
Just for full disclosure, I was originally returning an ArrayList of custom model objects and using an ArrayAdapter, but (understandably) the customer pointed out it was bad memory-manangement and I wasn't happy with the performance anyways. I'd really like to avoid a solution where I'm generating huge lists of objects and then doing a listAdapter.notifyDataSetChanged/Invalidated()
Here is the code in question:
private Runnable filterDrugListRunnable = new Runnable() {
public void run() {
if (filterLock.tryLock() == false) return;
cur = ActivityUtils.getIndexItemCursor(DrugListActivity.this);
if (cur == null || forceRefresh == true) {
cur = docDb.getItemCursor(selectedIndex.getIndexId(), filter);
ActivityUtils.setIndexItemCursor(DrugListActivity.this, cur);
forceRefresh = false;
}
updateHandler.post(new Runnable() {
public void run() {
listAdapter.changeCursor(cur);
}
});
filterLock.unlock();
updateHandler.post(hideProgressRunnable);
updateHandler.post(updateListRunnable);
}
};
I find it difficult to believe that listAdapter.changeCursor() alone would take up sufficient time to cause an ANR, assuming you created the Cursor in a background thread. There just should not be that much work that needs to happen to repaint a handful of list rows. I would double-check to see what work you are doing in your Handler is as limited as you think. Perhaps consider using an AsyncTask, which makes it easier to separate the background work (doInBackground()) from the on-UI-thread post-processing (onPostExecute()).
You can try just replacing the adapter outright, by calling setAdapter() again with the new Cursor wrapped in a new adapter.
You can look to see how AutoCompleteTextView handles this scenario, since it does on-the-fly filtering with a SpinnerAdapter. Perhaps some of its techniques can apply in your case.
Just posted an answer here: Android: Update Listview after Thread loads data from the net
Short: AsyncTask's method onProgressUpdate can touch the view: http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)