After answering this question, I got a doubt about the sense/usefulness of using the get() method of Android's AsyncTask class.
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves its result.
Basically, a synchronous solution to the AsyncTask class, that blocks (freezes) the UI until the background operations are finished.
Other than test purposes, and even in those cases, I can't really think in any scenario where it is actually a good solution, but I may be wrong, so I feel curious.
If you need the user to actually wait until the AsyncTask finishes, you can show a Dialog or ProgressDialog, having the control of the UI in every moment. I know it's not exactly the same, but IMHO it's a much better approach than using the get()
method.
What happens if we call Execute () more than once in async task? if we execute more than one AsyncTask at a time, they will run sequentially by the default version from Android 3.0 onwards.
AsyncTask must be subclassed to be used. The subclass will override at least one method ( doInBackground(Params...) ), and most often will override a second one ( onPostExecute(Result) .)
AsyncTask is used to perform time talking operations in android, but it's marked as deprecated from android 11. There are many alternatives are available for replacing an AsyncTask, one of the replacements is ExecutorService.
AsyncTask instances can only be used one time.
AsyncTask
isn't the only way of doing background operations. Indeed, the documentation says that AsyncTask
should only be used for operations take at most a few seconds. So if you've got tasks that take longer, they should be coded via classes that implement the runnable interface. Such tasks in other (non AsyncTask) threads may well want to wait for an AsyncTask
to finish, so it seems to me that the idea that there are no situations where one would want to use AsyncTask.get()
is false.
Update: In response to a comment, to emphasize that this could be a valid use of AsyncTask.get()
, the following is possible:
AsyncTask
s that get initiated from the UI thread, which might involve communicating over the internet, e.g. loading a web page, or communicating with a server. Whatever the results of the AsyncTask
are, some (or all) of the results are needed to update the screen. Hence an AsyncTask
with its doInBackground
followed by onPostExecute
on the UI thread makes sense.AsyncTask
, it places the AsyncTask
object in a queue, for additional processing by a separate background thread once the results are available.AsyncTask
in the queue in turn, the background thread uses AsyncTask.get()
to wait for the task to finish, before doing the additional processing. One obvious example of additional processing could simply be logging all such AsyncTask
activities to a server on the internet, so it makes sense to do this in the background.KickOffAsynctask(...)
whenever it wants to do an AsyncTask, and there's a background thread that will automatically pickup the task for post-processing once the task is complete.
public class MyActivity extends Activity {
static class MyAsyncTaskParameters { }
static class MyAsyncTaskResults { }
Queue<MyAsyncTask> queue; // task queue for post-processing of AsyncTasks in the background
BackgroundThread b_thread; // class related to the background thread that does the post-processing of AsyncTasks
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
queue = new ConcurrentLinkedQueue<MyAsyncTask>();
b_thread = new BackgroundThread(queue);
b_thread.Start();
}
void KickOffAsynctask(MyAsyncTaskParameters params) {
MyAsyncTask newtask = new MyAsyncTask();
newtask.execute(params);
synchronized(queue) {
queue.add(newtask);
}
}
static class MyAsyncTask extends AsyncTask<MyAsyncTaskParameters, Void, MyAsyncTaskResults> {
@Override
protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) {
MyAsyncTaskResults results = new MyAsyncTaskResults();
// do AsyncTask in background
return results;
}
@Override
protected void onPostExecute(MyAsyncTaskResults res){
// take required results from MyAsyncResults for use in the user interface
}
}
static class BackgroundThread implements Runnable {
// class that controls the post processing of AsyncTask results in background
private Queue<MyAsyncTask> queue;
private Thread thisthread;
public boolean continue_running;
public BackgroundThread(Queue<MyAsyncTask> queue) {
this.queue=queue; thisthread = null; continue_running = true;
}
public void Start() {
thisthread = new Thread(this);
thisthread.start();
}
@Override
public void run() {
try {
do {
MyAsyncTask task;
synchronized(queue) {
task = queue.poll();
}
if (task == null) {
Thread.sleep(100);
} else {
MyAsyncTaskResults results = task.get();
// post processing of AsyncTask results in background, e.g. log to a server somewhere
}
} while (continue_running);
} catch(Throwable e) {
e.printStackTrace();
}
}
}
}
Update2. Another possible valid use of AsyncTask.get()
has occurred to me. The standard advice is not to use AsyncTask.get()
from the UI thread, because it causes the user interface to freeze until the result is available. However, for an app where stealth is needed, that may be exactly what is required. So how about the following situation: James Bond breaks into the hotel room of Le Chiffre and only has a couple of minutes to extract all the data from the villian's phone and install the monitoring virus. He installs the app provided by Q and starts it running, but he hears someone coming so he has to hide. Le Chiffre enters the room and picks up his phone to make a call. For a few seconds the phone seems a bit unresponsive, but suddenly the phone wakes up and he makes his phone call without further thought. Of course, the reason for the unresponsiveness was the fact that Q's app was running. It had various tasks to do, and some of them needed to be done in a particular order. The app used two threads to do the work, namely the UI thread itself and the single background thread that processes AsyncTask
s. The UI thread was in overall control of all the tasks, but because some tasks needed to be done before other tasks, there were points in the app where the UI thread used AsyncTask.get()
while waiting for the background task to finish :-).
The get
method should never be used in the UI thread because it will (as you noticed) freeze your UI. It should be used in a background thread to wait for the end of your task, but generally speaking, try to avoid AsyncTask
as much as possible (WHY?).
I would suggest a callback or eventbus as a replacement.
if you run multiple asyncTasks in parallel , you might want that some tasks would wait for the result of others.
however, i think you should avoid running too many asyncTasks in parallel, because it will slow down the device.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With