I have an app in which the app flow is different from Android standard:
Standard: Pressing a button on activity A and showing loading on this activity while loading the data and building the views of activity B and only then show the next activity. (Call AsyncTask on activity A, when finished send data and call activity B)
What I need: Press the button on activity A, go to activity B, and while showing loading, update the view of Activity B behind the loading. (Move from activity A to B and there call AsyncTask while showing loading. When AsyncTask is finished update the view while the loading is on front thus showing the view update process)
Problem: This will make the loading icon stop.. and sometimes show the unresponsive dialog (due to the long taking of the operation) and using the UI thread to change a view that is being built.
I've read some questions about the same matter: Android: how to update UI dynamically?
But none has provided a generic answer.
If you answer is "that's not the recommended behaviour" i'll agree... but these are requirements so i'll really appreciate some help :-D
I first did this already a year ago in a project. I got this very same problem because I've tried to use an icon, and there were so much to be updated that the icon freezed sometimes, so I ended up using a Handler paired with AsyncTask. It's actually a very common pattern in pre-setup activities.
Those are the steps:
Handler object. You could use something like this (a Loading dialog instead of a Toast, obviously).AsyncTask doing your computations.publishProgress. Give flags to the code in order to tell it exactly which parts of the UI need to be build. You'll see the UI being build behind while your loading dialog is displaying and spinning.onPostExecute.Below is a sample code that does exactly what you describe:
private void settingsAndPlaceTaskStart() {
// loading dialog
startLoading();
new AsyncTask<Context, Integer, Void>() {
@Override
protected Void doInBackground(Context... context) {
// check and prepare settings integrity
Settings st = new Settings(context[0], false);
st.checkPreferencesIntegrity();
// set text for each view / paired object
// this will take a long time
do {
// ... removed for clarity
int code = ...;
publishProgress(mObjects.getViewByCode(code));
while (mObjects.getNext());
return null;
}
@Override
protected void onPostExecute(Void void) {
// finish stuff
}
@Override
protected void onProgressUpdate(Integer... message) {
prepareView(message[0]);
}
}.execute(getActivity());
}
Here the Loading does not suffer from any stutter while the progress is spinning in the dialog. The dialog stays in the foreground until the onPostExecute. You should dismiss the dialog in there, following the end of the task.
Let me make sure I have this right: Activity A is your first, B your second. You want a button on A that triggers 2 things: an async data load and a push of B on the Activity stack. This is all fine.
In "What I Need" you use the verb phrase "update the view in background". That is not possible - you can only update a view on the main UI thread. Also, once A's onPause() is called (triggered by the push of B), you really should consider A to be unavailable for processing. What you can do is load the data in the background, while B does its thing, and then A, in its onResume() can update its UI appropriately.
If I'm wrong and you have gotten A to do some UI work while B is presented, then good on you, but if your processing as a chunk is taking too long, then I guess you'll have to break it up into smaller chunks and schedule them bit by bit, as to not interrupt with the user's experience of B.
UPDATE
I'm not sure how you will accomplish working with the UI resources of Activity Y while within the confines of Activity X, especially if Y has not yet been onCreate()d. I don't know if it's possible to share layout resources between Activities, though it may be.
The link you posted above gets to it - I think the answer regarding using the Handler class is part of your solution. Also, read about Looper and Designing for Responsiveness. I think, in short, you will want to implement a Handler on your main thread which allows you to update the UI in little 100-200ms chunks (as suggested in Responsiveness), and, with high granularity, send messages into that Handler as you process little bits of data on a background thread. For example, if you're updating a ListView, you should be able to inflate one row at a time. Likewise if you're adding images to a GridView. Also, consider pre-loading resources, but not showing them, so that you can spend less time inflating when time is short.
This is as far as my thinking takes me at the moment, but I'm marking this as a favorite, because I think I'll have to do something similar in a few weeks. Keep us posted on what works for you. Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With