AsyncTask and error when executed twice - android

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.)"

Related

ANDROID: Running mutiple async tasks after the first one finishes

Basically title. I can run them all in a row or all at once. I need the first one to run to load data for the rest.
Any ideas?
Maybes using handler for the first one so that the code runs on a different thread and trigger the rest when that one completes:
Handler firstTask = new Handler(new Runnable() {
Run() {
//do code
//run rest of tasks
}
}
If you want to make sure that the first AsyncTask has finished and returned the required data before the rest are executed, then override the onPostExecute() method of the first AsyncTask and execute the remaining AsyncTasks inside it.
onPostExecute() is a methode called after the AsyncTask is finished, you can check for the correctness of the received data inside it before executing the other AsyncTasks also inside it.
Your AsyncTasks will be run in the order in which they are submitted and not concurrently, unless you explicitly use the ExecuteOnExecutor method. You can pass data between them accordingly.
Just to be clear, you don't have to do anything at all to make sure that the first task completes before the second (and so on) are run. Each will complete before the next is started, in submission order.

android async task usage in depending sequence of tasks

My App contains a function that takes time to load ( parsing files).
THe function is called at multiple user case, i.e. from multiple user triggered condition.
Besides, it is called when onCreate is called.
In simple word, the flow is:
User click/OnCreate trigger
Function to parse file
Post to windows
Other postprocessing
I hope the user can click cancel to stop parsing files.
I tried to use asynctask. I know I can put the function to onPostExecute.
But I assume onPostExecute is just for dismiss progress dialog. Or I have to move a lot of codes ( for different cases) to it. Not a good idea.
I do not suppose user to do anything during parsing files.
So, what is the best way to do so? Despite I know it is not good, I think i have to occupy the UI thread.
In simple word, I want to wait for "parsing files", but i do not want to occupy the UI thread, so user can click cancel.
update:
I tried. however, there is a problem:
I use asynctask. I called:
mTask = new YourAsyncTask().execute();
YourAsyncTask.get(); // this force to wait for YourAsyncTask to return.
DoSomethingBaseOnAsyncTaskResult();
YourAsyncTask.get() hold the UI thread. So, there is not loading dialog, and user cannot click cancel from the dialog. It seems I have to move every line after
mTask = new YourAsyncTask().execute();
to
OnPostExecute()
which i did not prefer to do so because DoSomethingBaseOnAsyncTaskResult() can be very different based on the return result. or else, it becomes do everything in YourAsyncTask()
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time.This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
CODING
To start an Async task
mTask = new YourAsyncTask().execute();
and to cancel that task
mTask.cancel(true);
More detail is available here
In order to use the AsyncTask API, one has to follow the steps described below:
Create a class which extends AsyncTask.
Fill in the generic types available as generics in the class for:
the task execution array parameters
progress array parameters
result array parameters
Implement the method doInBackground(Parameters... parameters). This
method must execute the job which is supposed to be quite demanding.
Optionally, one can implement methods for:
cancelling the task - onCancelled(...)
executing tasks before the demanding task - onPreExecute(...)
reporting progress - onProgressUpdate(...)
executing activities after the demanding task is finished
-onPostExecute(...).

Android Global Progress Dialog

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

How to end AsyncTask onBackPress() and also does it still run if it isnt finished?

I use AsyncTask in several activities.
i know how to Override onBackPress().
But when an AsyncTask is running i want to give the user the ability to go back even though the asynctask is still running.
How can I do this?
Also does an asynctask still run when activity that initiated it is closed before it finishes?
AsyncTasks run on until they complete or are cancelled. So in your case (the user presses Back and you end the main activity), the AsyncTask will carry on.
If you did want to end the AsyncTask from onBackPressed, the best you can do is to call
myAsyncTask.cancel(true);
but all that does is call the task's onCancelled() which can set a cancel flag that can be checked (usually) in doInBackground() - and if it is set the task can return.
Note that using cancel(true) does not stop the task. The docs talk about "interrupting" the task for the true case, but all they mean is that onCancelled will be called while doInBackground is running - at which point the task has an opportunity to set a flag that doInBackground can inspect.
For the true case, if the task does not implement onCancelled, and/or it does not set/inspect a flag, the task will complete doInBackground, but onPostExecute(Object) is never invoked - which is equivalent to the false case.
The async task will continue to run even if your application was closed. You have to be careful with that since your task will leak your context (keep it in memory) if it has a reference to it (so the activity) as long as your task is still running. You can avoid that by referencing your activity by a WeakReference.
You can stop a running task with cancel(true). A cancel will let the task finish its doInBackground but will never call onPostExecute. You could interrupt your background routine by checking isCanceled() and so return earlier since the task was killed.
I deleted one half of my post!
I did so confuse interrupt with a thread stop! Using true will of course NOT stop the actual thread. Thanks a lot to Torid and his answer which proved me wrong! Big lesson lernt, thanks for that!

Android 1.5: Asynctask doInBackground() not called when get() method is called

I am running into an issue with the way my asynctasks are executed. Here's the problem code:
firstTask = new background().new FirstTask(context);
if (firstTask.execute().get().toString().equals("1")) {
secondTask = new background().new SecondTask(context);
}
What I'm doing here is creating a new asynctask object, assigning it to firstTask and then executing it. I then want to fire off a separate asynctask when the first one is done and making sure it returns a success value (1 in this case).
This works perfectly on Android 2.0 and up. However, I am testing with Android 1.5 and problems start popping up. The code above will run the first asynctask but doInBackground() is never called despite onPreExecute() being called. If I am to execute the first task without the get() method, doInBackground() is called and everything works as expected. Except now I do not have a way to determine if the first task completed successfully so that I can tell the second task to execute.
Is it safe to assume that this is a bug with asynctask on Android 1.5? Especially since the API (https://developer.android.com/reference/android/os/AsyncTask.html#get%28%29) says that the get method has been implemented since API 3.
Is there any way to fix this? Or another way to determine that the first task has finished?
If you are going to block (via get()), why are you bothering with AsyncTask in the first place? The whole point of AsyncTask is to not block.
If you want to have SecondTask execute when FirstTask is done, have FirstTask execute SecondTask in FirstTask's onPostExecute().

Categories

Resources