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.
Related
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
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 figured out if I exit an activity while is running the AsyncTask in the middle, and when I try to start that activity again, I will have to wait until the previous AsyncTask to finish before the new AsynTask starts. I tried both thread.sleep and systemclock.sleep and it gives me the same result. Which make sense because I guess the thread that I closed and opened are the same. Its there a way to just cancel the AsyncTask if the user exit an activity? Because then the second time the user enter the same activity he wouldn't have to wait until previous finishes.
I tried asyntask.cancel(true) in onPause(), it doesn't work, same thing happened.
As I understand it, the only difference between Thread.sleep() and SystemClock.sleep() is that Thread.sleep() can be interrupted. That is, something like:
SystemClock.sleep(10*1000);
sleeps the calling thread for 10 seconds and that's that, you just have to wait. Whereas:
Thread.sleep(10*1000);
will also sleep the calling thread for 10 seconds. But if you have a reference to the sleeping thread from another thread, you now have the option of something like:
sleepingThread.interrupt();
which effectively wakes sleepingThread from its 10 second sleep.
In the context of your question, which is better for AsyncTask, I think it's still entirely up to your requirements. I don't know your exact code of course, but given your task's doInBackground is apparently doing some sleeping and given you want to be able to cancel your task at arbitrary times, Thread.sleep() might make more sense.
When my app is loading data in an AsyncTask, it shows a splash screen. Sometimes this data loading takes under a second and sometimes it takes much longer. However I want to ensure that the splash is up for at least 2 seconds if the data loading finished first, or otherwise wait until the data was done.
My first solution was to use a Countdown Timer, and two boolean values. When the processes would start, their booleans would be set to true. When the process was done, it would set it's boolean false. Then it would check if the other's boolean was false, and if it was dismiss the splash.
While this works, I feel like it is overly complicated and was hoping to find a more efficient or better solution.
I want to ensure that the splash is up for at least 2 seconds if the
data loading finished first, or otherwise wait until the data was
done.
You can asyncronously start a Thread(Splash) and AsyncTask for Loading data and call the new Activity on onPostExecute() of you AsyncTask.
Could you not use System.getCurrentTime(); To accomplish this?
At the start of the AsyncTask, call that method and store the result.
then, when the task finishes, call the method again and calculate the difference in the time values. If its not greater than 2000 milliseconds, have a while loop that continually requests the system time and compare the values until its equal to or greater than 2 milliseconds.
I have an activity which performs a bunch of SQLite inserts as its very last act before starting another activity which relies on the just-inserted data.
I have just moved all the db stuff into an AsyncTask...and, yep, you guessed it, the new activity is being called before the previous one's inserts have completed.
Now, I'm happy with the speed of my db operations, but, how do I make my app wait for the AsyncTask to finish before starting the next activity?
I was thinkig about starting it fromonPostExecute, but that feels wrong, although I don't know why it would be if it is.
Currently all I intend to do in pre/postExecute is show a default dialog...but, that's obviously also failing because the next activity is starting as soon as the asyncTask is started :)
No need for AsyncTask usage here, or is there just a simple way to say "woah, boy, wait a sec!"? :)
It's OK to launch the other activity on onPostExecute... in fact, it sounds reasonable in your case.