我见过几个关于取消AsynTask的other post,但我认为其中任何一个都没有解决问题。想象一下这种情况:
public class TestTask extends AsyncTask<Void, Void, Object> {
@Override
protected void onCancelled(Object result) {
running = false;
Log.i("Test", "onCancelled");
}
@Override
protected Object doInBackground(Void... params) {
try {
Log.i("Test", "cancelling");
cancel(true);
Thread.sleep(5000);
Log.i("Test", "Past sleep");
} catch (InterruptedException e) {
Log.i("Test", "InterruptedException", e);
}
return null;
}
}
想象一下,我想在下载过程中取消这个长达20秒的请求,例如,如果服务器对json请求的响应速度很慢。所以Thread.sleep(5000)可能是我要取消的HttpGet请求。但是,cancel方法被标记为final,所以我无法覆盖它并调用get.abort()。 onCancel挂钩发生在doInBackground之后并返回UI线程。一旦HttpGet请求开始,检查isCancel对我没有任何好处。
我解决这个问题的方法是在我的AsynTask上创建一个abort()方法并调用它。
public void abort() {
get.abort();
cancel(true);
}
但这似乎与Android谷物有点不同。有没有更好的方法来取消请求?
答案 0 :(得分:0)
在docs for HttpGet
中,没有提及线程安全性,因此以您描述的方式调用abort()
可能会导致意外结果(充其量)。您可以做的是在HttpGet
的构造函数中传递AsyncTask
对象,或者通过设置器传递(只要您在调用AsyncTask.execute()
之前执行此操作)。
如果任务已被取消,您必须定期检查doInBackground()
内部:
@Override
protected Object doInBackground(Void... params) {
// start GET request
try {
Log.i("Test", "cancelling");
cancel(true);
Thread.sleep(5000);
Log.i("Test", "Past sleep");
if ( this.isCancelled() ) {
// abort GET request and/or stop doing other work
return null;
}
else {
// do what ever work you need to
}
} catch (InterruptedException e) {
Log.i("Test", "InterruptedException", e);
}
return null;
}
每当您觉得应该停止任务时,您都可以随时致电AsyncTask.cancel(true)
{3}}
答案 1 :(得分:0)
我不确定这是否适用,但您可以使用执行下载任务的执行程序服务创建另一个线程,并继续检查isCancelled()
内的doInBackground()
或直到将来的对象返回,以先发生者为准:
@Override
protected Object doInBackground(Void... params)
{
Callable<Void> downlaodTask = new Callable<Void>()
{
@Override
public Void call() throws Exception
{
// download task here
return null;
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(downlaodTask);
while(true) // check every second
{
try
{
future.get(1, TimeUnit.SECONDS); // wait until the download task finishes with 1 second as a timeout
break;
}
catch(TimeoutException e)
{
if(isCancelled())
{
executor.shutdownNow(); // or abort() or both
break;
}
}
}
return null;
}