Ali Ali - 1 month ago 8
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>
{
@Override
protected void onPreExecute() {
super.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
if(((System.currentTimeMillis()-startTime)/1000)>30)
{
cancel(true);
}
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.

Thanks.

Answer

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;
    }

     @Override
     public void run() {
        if (task.getStatus() == AsyncTask.Status.RUNNING )
            task.cancel(true);
     }
}

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);
task.execute(...)

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

if(taskCanceler != null && handler != null) {
     handler.removeCallbacks(taskCanceler);
}

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());

Comments