Ali Ali - 11 months ago 57
Android Question

Cancel AsyncTask after some time

This could be a duplicate question but I did not find what I was looking for.
I am calling an AsyncTask in the UI activity

new LoadData().execute();
and in doInBackground I call a method which takes time. I want to interrupt this thread if the data is not return after some time.
Below is the code how I tried to do this.

class LoadData extends AsyncTask<String, String, String>
protected void onPreExecute() {
startTime = System.currentTimeMillis();
protected String doInBackground(String... args)

DataCollector dc = new DataCollector();
data = dc.collectData(query);
//Here I check if the time is greater than 30 seconds then cancel
return null;

But this does not stop the task after 30 seconds, in fact it is taking more time.
I have tried
get(long timeout, TimeUnit unit);
as well but that does not work either.

Can anyone show me how can I do it or how do I use isCancelled() in doInBackground.


Answer Source

You need a thread that cancels your task after a certain amount of time. That Thread could look like this:

public class TaskCanceler implements Runnable{
    private AsyncTask task;

    public TaskCanceler(AsyncTask task) {
        this.task = task;

     public void run() {
        if (task.getStatus() == AsyncTask.Status.RUNNING )

And when you call your AsyncTask, you need to run the cancle task after a certain amount of time (=the timeout, in this case 20 sec)

private Handler handler = new Handler();
private TaskCanceler taskCanceler;
LoadData task = new LoadData();
taskCanceler = new TaskCanceler(task);
handler.postDelayed(taskCanceler, 20*1000);

It's a good idea if you clean this up on cancel or finish with

if(taskCanceler != null && handler != null) {

You can of course wrap this in an custom implementation of AsyncTask. I've used this pattern many times and it works like a charm. One thing to note, in rare cases the handler would not start, I suspect if you create it in the wrong context it will not survive in certain instances, so I forced the handler to be an the UI Thread with handler= new Handler(Looper.getMainLooper());