I have an activity which makes periodic requests (once every 15 seconds to get a json data feed). The requests I am passing off to a AsyncTask so its not on the main UI thread. So far so good. But lets say that I request the feed and it takes 20 seconds to respond. I really don't want to kick off another thread until say 30 seconds are up. So ....
Is there a way to prevent the AsyncTask from running if there first one has not yet finished?
Also is there a way to timebox the AsyncTask to take no more than 30 seconds? reguardless of the Http timeout?
Thanks,
Steve
You can use a mutex variable to enforce this. Say, We call the variable update. This will be a boolean variable with initial value true.
Before running an Async task, Check the value of update, If it is true run the async task and set update to false.
After the end of the async task, in the onPostExecute() method, set update to true again.
So another async task will not be launched while one hasn't finished, thus ensuring exclusivity.
Related
I use an asynctask in my app that downloads some data from the internet. If this task is executed twice within seconds, user presses the button twice, I get an IllegalState error saying a task can not be execute twice. If the user waits about 30 seconds, everyting is fine.
Then I tried to use AsyncTask.getStatus(), like this, to only execute when the task was NOT RUNNING, ie executed when status was PENDING or FINISHED, but this only worked the first time when the getStatus() was PENDING. If it was FINISHED, the same IllegalState error was produced.
Then I tried to follow an other example, saying the a new object of the AsyncTask should be created each time it is supposed to be executed. This seems to work.
So my question is, is it not possible to use one instance of an asynctask object and reexecute it? If so, how come it can be done if you wait long enought (like 30 seconds)?
No. You cannot execute the same async task twice. You are able to do it again after 30 secs because the async task completes processing and returns the result from doInBackground(). Hence you need to create an object every time or use a progress dialog to block the user from clicking on the button again. Show the progress dialog in onPreExecute() and dismiss in onPostExecute().
You can use one instance of an asynctask object and reexecute it, I use this and work for me:
if(yourAsyncTaskInstance!=null &&
yourAsyncTaskInstance.getStatus() == AsyncTask.Status.FINISHED){
yourAsyncTaskInstance = new YourAsyncTaskClass();
yourAsyncTaskInstance.execute();
}
WIthout seeing your code, it's difficult to know why it might be working after a 30 second wait, but, you are correct: as the docs say, "The task can be executed only once (an exception will be thrown if a second execution is attempted.)"
I am working on async task. When i call execute() on async task it takes 1 second to call doInBackground() method of async task which I don't want. Does anyone knows how to reduce that time?
Such things are up to the System. Never assume anything about timing when working multithreaded!
Anyways, if your AsyncTask repeatedly does the same work, try using an ExecutorService which gets a Runnable as argument. The ExecutorServices don't destroy the created threads automatically but try to re-use it. That way the starttime might be reduced.
One second to call doInBackground(), or one second to return a result? The reason for using an AsyncTask is to perform longer operations asynchronously from the UI thread. Performing operations that take a while (eg. 1 second) is why they exist.
instead of execute() use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ...) That way you don't need an ExecutorService.
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 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 have an activity that displays a number. The number is obtained from SharedPreferences e.g
int num=pref.getInt(myAsyncTask.MYNUMBER,0);
The SharedPreference is loaded inside an AsyncTask where calculations take place (that involve retrieving data from db and so on). So, OnCreate() of the activity I run the Asynctask to calculate the value. However, the value is not always updated to the latest one when I launch the activity. This might be because Asynctask takes more time to calculate the new value than the the action of displaying the value inside the activity. How can I delay the execution of the method displaying the value until the Asynctask finishes with the process of the new one?
[[EDIT]]
I removed sharedpreferences. I use the onPostExecute() method to get the result. However, the behaviour is similar. The result is returned after the value is displayed so i couldn't see anything at all.
If the calculation doesn't take more than few second, the simplest solution is to use AsyncTask.get(), this method will block UI thread execution and make UI thread waiting for AsyncTask to finish:
public void onCreate(Bundle savedInstanceState) {
... ...
MyAsyncTask myAsyncTask = nee MyAsyncTask();
myAsyncTask.execute();
myAsyncTask.get(); // alternatively you can use AsyncTask.(long timeout, TimeUnit unit)
... ...
}
Bear in mind that it blocks UI thrread execution, if your calculation is longer than 5 seconds, you will probably get ANR exception.
Since you already use AsyncTask, a more reasonable solution is moving execution of the method displaying the value into AsyncTask.onPostExecute(), this is the exactly reason why AsyncTask exist in API to solve this kind if scenario.
Just use listener concept, or just 'pass' your Activity to your asynctask so It can call the main thread.
If the value is not showing as correct at the time you launch the activity you should set the visibility of the View to View.GONE so it doesn't appear, then change the visibility back to visible when you have the result. To update the value you could implement a listener on your activity that gets called by the AsyncTask.
If its going to take a significant time (more than a few seconds) you might want to also use a progress dialog so the user understands that they need to wait.