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().
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.)"
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 Asynctask Generally Understanding Questions.
If I want to make Asynctask SyncTask, how do I do that?
AsyncTask A = new AsyncTask();
AsyncTask B = new AsyncTask();
A.execute();
B.execute();
If I want A to finish before B starts how should I do that?
If I close an Activity, does the AsyncTask call on that activity gets destroy?
If I close the whole application, does the AsyncTask call on that application gets destroy?
call b.execute() in onPostExecute() of A
AsyncTask is an abstract class so you must extend it in order to add your app specific functionality to it. You implement the doInBackground() method to do what ever work is required. The AsyncTask documentation explains it in detail. I will give a brief answer to each of your question.
If I want to make Asynctask SyncTask, how do I do that?
You have the right idea with creating the async task, however as I mentioned before you have to subclass the async task to actually do some work.
Here is an example (note that the Void types do have meaning however the documentation covers them in great detail)
public class MyTask extends AsyncTask<Void, Void, Void>
{
//This method will run on the back ground thread
#Override
protected Void doInBackground(Void... params)
{
// All the heavy work should be done here e.g.
// loading from network, database etc.
return null;
}
}
Then in your activity you would create and run this task as follows :
MyTask myTask = new MyTask();
myTask.execute()
If I want A to finish before B starts how should I do that?
As the documentation states:
When first introduced, AsyncTasks were executed serially on a single
background thread. Starting with DONUT, this was changed to a pool of
threads allowing multiple tasks to operate in parallel. Starting with
HONEYCOMB, tasks are executed on a single thread to avoid common
application errors caused by parallel execution.
Which means if you are using honeycomb or later async tasks will run on a single thread. So normally A should get executed before B if you execute in that order. But I would do something like this: Launch A, then when onPostExecute() of A gets called, you know that A is done, you can start your task B from this method to be sure that A finishes before B.
If I close an Activity, does the AsyncTask call on that activity gets
destroy?
The short answer to this question is No. The async task will continue to run even if the activity has called on destroy. However if the async task is tied to the activity life cycle you need to make sure you end the task when the activity dies or you will run into problems.
If I close the whole application, does the AsyncTask call on that
application gets destroy?
I am not 100% sure about this one. I believe the behavior is unspecified since now its up to Android to collect resources. It may decide to kill the task right away if its low on resources or it may not. However you should avoid this design. If you need to run something after your application has closed, then look at the Service class.
Take a look at http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html#.VNtB1LDF_38 it may help you.
I am new to instrumentation testing in Android. Can someone show me how i can start an async task and wait for the result to be computed ? Many of my network calls rely on AsynTasks and i need to know how we can test it ? For activities we have a getInstrumentation().waitForMonitor , what can we do for AsyncTasks ?
The AsyncTask class has a blocking get() method that will basically wait for the task to finish before it returns. It's the synchronous version of calling execute(), which means you could think of it as the background work being executed on the main thread - hence it blocks until finished.
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves
its result.
Is it possible to execute an AsyncTask from Runnable? in my experience it can be done, but not safely. When my app first runs my AsyncTask runs fine from the Runnable. But when the app is moved to the background, then brought back forward I get "Can't create handler inside thread that has not called Looper.prepare()".
Here's what I'm trying to do:
I'm using MapView and invoking runOnFirstFix(Runnable) within onCreate. My Runnable calls an AsyncTask to perform a web service call which returns some data based on the location.
I move the app to the background (by tapping the home button), after some time I bring my app forward again and I'm getting the exception at the point where I'm invoking execute() on my AsyncTask.
First of all, why is runOnFirstFix being executed again? Secondly, why is it causing the exception the second time around?
I'm guessing that there is some part of the lifecycle that I don't understand.
Thanks.
It wasn't initially obvious to me that the AsyncTask needed to be called from the UI thread. So when runOnFirstFix ran the second time it was from withing a Runnable which wasn't on the UI thread. To solve the problem I simple created another Runnable inside the first to run the AsynchTask.
And the reason my runOnFirstFix seemed to be called twice was simply because I was creating a new instance of it.