Ideal way to cancel an executing AsyncTask
I am running remote audio-file-fetching and audio file playback operations in a background thread using AsyncTask
. A Cancellable
progress bar is shown for the time the fetch operation runs.
I want to cancel/abort the AsyncTask
run when the user cancels (decides against) the operation. What is the ideal way to handle such a case?
Solution 1:
Just discovered that AlertDialogs
's boolean cancel(...);
I've been using everywhere actually does nothing. Great.
So...
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
private final ProgressDialog progressDialog;
public MyTask(Context ctx) {
progressDialog = gimmeOne(ctx);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// actually could set running = false; right here, but I'll
// stick to contract.
cancel(true);
}
});
}
@Override
protected void onPreExecute() {
progressDialog.show();
}
@Override
protected void onCancelled() {
running = false;
}
@Override
protected Void doInBackground(Void... params) {
while (running) {
// does the hard work
}
return null;
}
// ...
}
Solution 2:
If you're doing computations:
- You have to check
isCancelled()
periodically.
If you're doing a HTTP request:
- Save the instance of your
HttpGet
orHttpPost
somewhere (eg. a public field). - After calling
cancel
, callrequest.abort()
. This will causeIOException
be thrown inside yourdoInBackground
.
In my case, I had a connector class which I used in various AsyncTasks. To keep it simple, I added a new abortAllRequests
method to that class and called this method directly after calling cancel
.
Solution 3:
The thing is that AsyncTask.cancel() call only calls the onCancel function in your task. This is where you want to handle the cancel request.
Here is a small task I use to trigger an update method
private class UpdateTask extends AsyncTask<Void, Void, Void> {
private boolean running = true;
@Override
protected void onCancelled() {
running = false;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
onUpdate();
}
@Override
protected Void doInBackground(Void... params) {
while(running) {
publishProgress();
}
return null;
}
}
Solution 4:
Simple: don't use an AsyncTask
. AsyncTask
is designed for short operations that end quickly (tens of seconds) and therefore do not need to be canceled. "Audio file playback" does not qualify. You don't even need a background thread for ordinary audio file playback.