I have an AsyncTask class that handles all networking calls for my app. I also have a Globals class that holds a progress dialog. Now, what I want is for there to only be one progress dialog at a time; this is fairly simple. The Globals class initializes the dialog, and each time it is used by the AsyncTask, only the message is changed. My issue is determining when to dismiss it. If I use p.dismiss() at the end of onPostExecute(), then the progress bar will go away until the next AsyncTask runs, which is not what I want. However, if I don't include the line there, then the progress dialog will stay up indefinitely. I guess what I'm trying to find is a way to see if all AsyncTasks have finished running. By doing this, then that one global progressdialog will be able to close without looking wonky.
Chaining together all the AsyncTasks is not an option (e.g. having the first one execute the second in its onPostExecute()).
Also note that there could be anywhere between one and five AsyncTasks running at the same time.
How can I determine if every AsyncTask is complete?
you could keep track of how many you are starting and create a callback to the class every time a task finishes, then when the returned count matches the start count you know all the tasks are done.
there really is no way to know when see what tasks are running without doing some thing like that.
there is a getStatus but you would have to keep polling for the status to see if the individual task is done or not
Related
I have a activity that show one listview. In the activity I have a one AsyncTask (named here of AsListView) to get values from internet and fill some informations in each item of the listview. Work fine.
Now I created a button in ActionBar to show one image from streetview. To do this I have implemented another AsyncTask (named here of AsImage) to get image from google and show in a DialogFragment, but is necessary wait the execution of all AsListView Threads. It spends long time depending of the number of items in the list.
To execute AsImage rapidily, I cancel all AsListView tasks, but it's not good for me (user loss informations). The ideal soluction is set AsListView tasks to wait while AsImage execute. When AsImage finish I set AsListView tasks to continue execution. But I know that is not possible handle the control of execution of AsynkTasks.....
Some solution?
You can try to synchronize the AsyncTasks using a CountDownLatch.
Otherwise if you want you can use Threads instead of AsyncTasks and set their priorities, but there is a reason android made the AsyncTask class so I recommend you use it.
I know it sounds crazy that someone is using runOnUiThread inside AsyncTask. Somehow, it is working for me but I wanna know if it is an acceptable and robust approach or not. Here is the scenario:
I have an app in which after successful login, user is rendered to next screen. In this new screen, 3 different methods are loading different types of data from a web server. These methods are:
getMembersForList() : It loads the list of community members and shows it in a listview.
getProfileData() : It loads the profile of logged in user and shows his name , image etc on the screen.
getNotificationCounts : It loads the count of new notifications for the user.
I applied 3 different approaches for it :
(1) Calling all 3 methods simply in onCreate i.e. no exclusive thread is being used for any of the methods . In this case , the transition from login screen to this screen becomes very slow and black screen shows up for some time before this activity shows up.
(2) Calling getMembersForList() on UI thread and the other 2 methods on exclusive threads. In this case transition becomes fast and list shows up quickly but Notification counts and username etc. don't show up because WrongThreadException occurs saying that this thread can't touch other thread's views (TextViews for username, notification count etc. which are declared globally) . The same thing happens when I start these threads from an AsyncTask as well.
(3) Calling getMembersForList() on UI thread and then starting an AsyncTask in which the other 2 methods are being called in "runOnUiThread" inside doInBackground() method. This solves both the above issues. Now the screen transition is faster and the WrongThread exception is also not occuring.
So far the approach-(3) is working good for me but I am not sure if this is the right way to do it because runOnUiThread and AsyncTask are 2 completely opposite things. Can anyone please clear my doubts about this scenario. Thanx in advance.
Yes, use-cases like this are a big reason why the runOnUiThread() method exists in the first place. The idea is you allow your background thread(s)/AsyncTask instance(s) to run your lengthy operations in the background, and then provide a simple hook that they can use to update the interface when they have the result (or at arbitrary intervals, as different pieces of the result become available).
As long as that's what you're doing, then your usage is fine. What you want to avoid doing is performing a lengthy operation on the main thread, either directly or indirectly by passing in some lengthy operation from a background thread.
Of course you don't have to do it that way if you don't want to. You could use postExecute() instead. Or you could store the result somewhere and then use any sort of message-passing API to notify the main thread that the result is ready, and so on.
I would advice to run all the 3 calls in the asyncTask, and update the UI in the postExecute() of the AsyncTask after the background taks is complete, postExecute runs on UIthread so you need not call anything explicit to run them on UIthread.
I have two total different implementations of AsyncTask, lets say AT1 and AT2.
AT1 is executed first, then AT2 is executed. AT1 waits in doInBackground until AT2 has done its task by polling this data every 500 ms. But this never happens.
So what I basically want is this:
But what seems to happen is this:
Except AT1 is never done, and AT2 is never started.
Is there a way I can force these two AsyncTasks to be executed on two seperate threads, or is there another solution for this?
It is not possible to first start AT2 and after that execute AT1.
EDIT
For clarification: AT1 is executed when a user opens a particular screen, and needs to download data for that screen, based on a location. AT2 is executed on Location change, and when that happens, some calculations are made that cannot be done on the UI thread.
When AT2 has never been executed, AT1 has no location to download data for, so it needs to wait for AT2 to finish. When AT2 has been executed, the location data is already there, and AT1 doesn't need to wait.
Also, this problem occurs in ICS, not in Android 2.3, like this answer suggests.
When I posted this question, this question appeared in the Related section.
It advices to use executeOnExecutor, I've implemented this as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new SetLocationAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
new SetLocationAsyncTask().execute(location);
}
What's the point of having two async tasks, if one waits for the other? And if you want to do it, why not have the first one start the second one and put the "done" stuff in the second task?
Sounds like you may need to rethink your logic - if you're kicking off a thread which then needs to wait for another thread to do some work, why not just have the first thread do that work?
If you really need 2 AsyncTasks, have the first one gather whatever data is needed and don't kick off the second until after the first is finished - have a read about onPostExecute in the docs.
I've got an app that uses ListActivity to give users a list of actions. When they click one I use an Intent to launch a separate activity.
My problem is that the actions that the app performs take about 20 seconds to finish, and since I don't want the user to receive that nasty ANR dialog, I tried to use AsyncTask to present them with a loading screen in the mean time. I tried using setContentView(R.layout.loading); on onPreExecute(), but it throws a NullPointerException which as far as I have figured out is due to the fact that loading.xml is not "a ListView whose ID is android.R.id.list".
So what can I do now? How can I show that loading screen? Is there a way around this pretty annoying situation? Any help would be greatly appreciated. Thanks!
I am not sure exactly what your use case is; you have a list of items that are populated immediately, and upon selecting one an action is taken? The action that is taken is to launch another Activity which performs background processing?
Or does it take that long to populate the list of actions?
If the former, you can use an AsyncTask for the long-running activity instead of an Intent to launch another Activity: in the callback you get for the click on the item in question, you would create the AsyncTask, and in doInBackground you would perform the long-running activity, with onPostExecute refreshing or manipulating your list as necessary.
Another thing to consider is using a dialog box to show a loading screen, if the loading is required to happen before you launch a new Activity.
If you can further describe your use case, I can help you more.
It's not the loading screen you need to have on the AsyncTask, it's that 20-second Activity initialization. I would look for a way to do all the setup in a background thread in a Service while the user is free to merrily bop around in other Activities. I'd try hard to find a way not to just stall the user for 20 seconds. Maybe take them to the target Activity and show them data cached from their last visit until the new set is ready.
Fire up and display your loading dialogs in your onCreate() of the Activity being called, then call Dialog.dismiss() in your AsyncTask's onPostExecute().
I'm currently using an AsyncTask to make an API call and populate a list with data.
I have a Sub Menu whose items can call the AsyncTask to populate the data, problem is that if i click quickly i end up with merged results obviously cause the AsyncTask is running at the same time as each other.
What is the best way to handle a situation like this? Sorry if this is a amateur question.
I would use a ProgressDialog to show that content is being updated, and when the update is complete, dismiss() the dialog. While this is happening, you should make sure that you are not accepting touch input on your ListView. (this may happen by default when the ProgressDialog is in front, I am not remembering currently...)
Take a look at this link for an example.
You could configure only a single Asynch task to run at a time.
A boolean variable which is set to true as soon as the asynch task starts and set to false as soon as it finishes.
Next call could wait for this to be set to false. You could also rate limit what is the min time after which only making the API call makes sense.