调用cancel(true)后AsyncTask.onCancelled()未被调用

8

运行在2.3.6设备上的Android SDK v15。

我遇到了一个问题,即在doInBackground()中调用cancel()后仍然会调用onPostExecute()

以下是我的代码:

@Override
public String doInBackground(String... params) {
    try {
        return someMethod();
    } catch (Exception e) {
        cancel(true);
    }

    return null;
}

public String someMethod() throws Exception {
    ...
}

我正在强制执行someMethod()抛出异常以进行测试,但是不管怎样,我总是返回到onPostExecute()而不是调用onCancelled。如果我检查isCancelled()的返回值为true,那么我知道cancel(true)已经被执行。

你有什么想法吗?

2个回答

24
根据 Android API 文档,onCancelled() 存在于 API 级别 3,而 onCancelled(Object result) 仅在 API 级别 11 及以上版本中添加。因此,如果平台的 API 级别低于 11,则始终会调用 onCancelled(),否则将始终调用 onCancelled(Object)
因此,如果您想在所有 API 级别为 3 及以上的系统上运行代码,则需要实现这两种方法。为了使行为相同,您可能希望将结果存储在实例变量中,以便可以像下面示例那样使用 isCancelled()
public class MyTask extends AsyncTask<String, String, Boolean> {
  private Boolean result;
  // . . .
  @Override
  protected void onCancelled() {
    handleOnCancelled(this.result);
  }
  @Override
  protected void onCancelled(Boolean result) {
    handleOnCancelled(result);
  }
  //Both the functions will call this function
  private void handleOnCancelled(Boolean result) {
    // actual code here
  }
}

顺便说一下,Eric的代码可能不起作用,因为Android API文档中写道:

调用cancel()方法将导致在UI线程上调用onCancelled(Object),在doInBackground(Object[])返回后。 调用cancel()方法可以确保永远不会调用onPostExecute(Object)


1
答案不错,但方法名存在拼写错误。我猜应该是“handleOnCancelled”。 - TonyQ
1
调用cancel()方法保证不会触发onPostExecute(Object),这只适用于蜂窝及更高版本,对于早期版本请参考@eric的答案。 - Ahmad Dwaik 'Warlock'

7

onCancelled 仅支持 Android API level 11 (Honeycomb 3.0.x) 及以上版本。这意味着,在一个 Android 2.3.6 设备上,它将不会被调用。

你最好是将此代码放在 onPostExecute 中:

protected void onPostExecute(...) {
    if (isCancelled() && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        onCancelled();
    } else {
        // Your normal onPostExecute code
    }
}

如果你想避免版本检查,可以使用以下方法替代:
protected void onPostExecute(...) {
    if (isCancelled()) {
        customCancelMethod();
    } else {
        // Your normal onPostExecute code
    }
}
protected void onCancelled() {
    customCancelMethod();
}
protected void customCancelMethod() {
    // Your cancel code
}

希望能帮到您!:)

@Radu,我不知道你正在使用的代码或者你想要完成的任务。如果你一直在尝试类似的操作并且遇到了问题,最好还是开一个新的问题来询问。 - Cat
我的观点是我无法覆盖onCancelled(SomeType result)和简单的onCancelled()。此外,如果我针对旧版Android版本,根本不会调用onCancelled()... - Radu
@Radu 这篇帖子的重点就在于,如果你正在旧版 Android 上运行程序,那么你需要手动调用 onCancelled()。此外,不要以较旧的版本为目标(这就是为什么你无法覆盖它的原因)。你的目标应该是最新的 SDK 版本,而你的最低支持版本应该是你想要支持的最低版本。 - Cat
我曾经遇到过同样的问题,你的答案为我打开了天堂之门 :) +1 - Ahmad Dwaik 'Warlock'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接