Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android calling AsyncTask right after an another finished

I have some problem with Android AsyncTask. There is an Activity which contains some TextView a button and a picture. When an user entered this activity I start an asynctask to check whether the user can go toward from the activity (until the task not finish the button not active). Then I want to start another asyntask to get the picture. So I made an inner class:

AsyncTask<String, Void, JSONObject>() authTask = new AsyncTask<String, Void, JSONObject>() {
     @Override
     protected JSONObject doInBackground(String... params) {
         //call the rest api
     }
     @Override
     protected void onPostExecute(JSONObject result) {
         // check the result
         // and make another asynctask
         AsyncTask<String, Void, Bitmap> imageTask = new Async.... {
             // get image
         }
         imageTask.execute();
     }
}

and I call authTask.execute(); from the UI thread.

I have a bad feeling about this, especially it seems doesn't work (it's ok few times but suddenly it "freeze": no exception just hanging and the progress bar is spinning. Nothing happens and the button won't be active.) There is another way to get an information and when it's finished immediately start another task?

UDPATE: I working with api level 10. In authTask I get some information which is needed to start imageTask (some id) so I have to call these tasks in a row. In api level 10 it's is possible?

Thanks in advance!

Br, Peter

like image 729
hcpeter Avatar asked Apr 06 '12 20:04

hcpeter


People also ask

What happen if we call execute more than once in AsyncTask?

Limitation Of AsyncTask There is a limit of how many tasks can be run simultaneously. Since AsyncTask uses a thread pool executor with max number of worker threads (128) and the delayed tasks queue has fixed size 10. If you try to execute more than 138 AsyncTasks the app will crash with java.

How many times an instance of AsyncTask can be executed?

AsyncTask instances can only be used one time.

What is the problem with AsyncTask in Android?

In summary, the three most common issues with AsyncTask are: Memory leaks. Cancellation of background work. Computational cost.

Why did AsyncTask get deprecated?

This class was deprecated in API level 30. AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes.


4 Answers

you can use getStatus() checks whether the the AsyncTask is pending, running, or finished.and when finsh start your new task.like:

if(authTask .getStatus() == AsyncTask.Status.PENDING){     // My AsyncTask has not started yet }  if(authTask .getStatus() == AsyncTask.Status.RUNNING){     // My AsyncTask is currently doing work in doInBackground() }  if(authTask .getStatus() == AsyncTask.Status.FINISHED){     // START NEW TASK HERE } 

example for your app:

btn.setOnClickListener(new View.OnClickListener()   {     public void onClick(View v)       {         if (authTask != null && authTask.getStatus() == AsyncTask.Status.FINISHED) {            //START YOUR NEW TASK HERE         }         else         {           //IGNORE BUTTON CLICK         }       }    });  
like image 200
ρяσѕρєя K Avatar answered Sep 21 '22 16:09

ρяσѕρєя K


1:

You could write the code for authTask and then for imageTask, one after the other, within a single doInBackground(). This single AsyncTask instance would be fire by a single execute() statement. This may or may not be practical depending on needed UI interactions.


2:

Edit: as noted by kabuku this information is mostly for HoneyComb+. Pre HoneyComb I would definitely go with option 1 above. executeOnExecutor() is api level 11+

In receent versions, execute() will send your AsyncTasks in series by default (ICS+). If you want to make sure this happens, specify the serial executor.

In your case this would be:

authTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); // Image task will only be done AFTER textViewTask is done imageTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); 

And for newer versions a simple

... // ICS+ and pre honeycomb (I think) authTask.execute(); // Image task will only be done AFTER textViewTask is done imageTask.execute(); ... 

From the AsycnTask.execute() documentation:

Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. 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. After HONEYCOMB, it is planned to change this back to a single thread to avoid common application errors caused by parallel execution.


PS: To run tasks independent of each other you must use the AsyncTask.THREAD_POOL_EXECUTOR. That requires a different executor:

// Go parallel! (NOT what you want) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
like image 38
Peter Ajtai Avatar answered Sep 19 '22 16:09

Peter Ajtai


Its not a good design to nest AsyncTask. Do all the heavy lifting in doInBackground and simply post/update the results. In other words, combine the processing of second AsyncTask in your first one.

like image 43
waqaslam Avatar answered Sep 19 '22 16:09

waqaslam


From the code that you showed it does not seem to make sense to spawn second task. Just get you image inside doInBackground of the first task right after authorization. If you need to update UI in between, you can do it in progress update.

like image 39
Alex Gitelman Avatar answered Sep 21 '22 16:09

Alex Gitelman