当在android中调用AsyncTask.cancel(true)时,AsyncTask不会立即调用`onCancelled`

时间:2016-07-16 10:05:11

标签: java android multithreading android-asynctask

我有一个AsyncTask调用web服务并从中获取一个json对象。我想为此任务设置超时,以便在出现任何问题时(例如互联网连接断开等),AsyncTask将被取消。 到目前为止,这是我的代码:

@Override
protected void onStart() {
final GetRequestsTask requestTask = new GetRequestsTask();
requestTask.execute(createUrl());
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
      @Override
      public void run() {
          Log.d("myapp", "entered handler");
          if (requestTask.getStatus() == AsyncTask.Status.RUNNING) {
              Log.d("myapp", "entered cancelling");
              requestTask.cancel(true);
          }
      }
}, TIME_OUT);
}

问题是当handler到达"进入取消"指向并将取消信号发送到AsyncTask,它不会立即取消并立即拨打onCancelled()(如果有的话,将在10秒左右后调用)

我的GetRequestTask是线性的,这意味着它内部没有循环,因此我无法在isCancelled()方法中手动检查doInBackground()

你建议我做什么?

2 个答案:

答案 0 :(得分:1)

来自this question

如果您正在进行计算:

  • 您必须定期检查isCancelled()。

如果您正在执行HTTP请求:

  • 将HttpGet或HttpPost的实例保存在某处(例如公共字段)。
  • 调用cancel后,调用request.abort()。这将导致在doInBackground中抛出IOException。

另外如果您使用某个库来提供方便的请求,那么我认为它应该有一些 cance()方法。例如,对于retrofit there is such method.

因此,在这种情况下,如果你正在做一个HTTP请求'部分。你需要:

  • 保存您的请求实例(以便对其进行改造)
  • 致电取消后,请致电'取消'保存请求实例的方法。

还有一个替代方案是rxJava。在此库的帮助下,您可以为您的请求创建Observable并保存对其子项的引用。然后你只需要调用savedSubscription.unsibscribe()就可以了。

答案 1 :(得分:0)

是的,Asynctask需要一些时间来调用onCancelled。基本上,当doInBackground返回时,它将调用onCancelled()。 为了解决这个问题,您可以经常在doInBackground中检查isCancelled(),并在它返回true时立即引发异常。它将退出doInBackground并立即调用onCancelled()回调方法。