【问题标题】:AsyncTask.onCancelled() not being called after cancel(true)AsyncTask.onCancelled() 在 cancel(true) 之后没有被调用
【发布时间】:2012-06-23 00:50:01
【问题描述】:

在 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() 抛出一个异常来测试它,而不是调用onCancelled,我总是返回onPostExecute()。如果我检查isCancelled(),返回值为真,所以我知道cancel(true)正在被执行。

有什么想法吗?

【问题讨论】:

    标签: android android-asynctask


    【解决方案1】:

    根据 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() 方法将导致onCancelled(Object)doInBackground(Object[]) 之后在UI 线程上被调用 返回。 调用 cancel() 方法可以保证 onPostExecute(Object) 永远不会被调用。

    【讨论】:

    • 好答案,但方法名称存在拼写错误。我想应该是“handleOnCancelled”。
    • 调用cancel()方法保证onPostExecute(Object)永远不会被调用,这仅适用于honeycomb,较早版本参考@eric回答
    【解决方案2】:

    onCancelled 仅从 Android API 级别 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 我不知道您正在使用的代码或您要完成的任务。如果您一直在尝试做类似的事情并且遇到问题,那么您最好开始一个新问题。
    • 我的观点是我不能 @ 覆盖 onCancelled(SomeType 结果) 和简单的 onCancelled()。另外,如果我针对的是旧的 Android 版本,则根本不会调用 onCancelled()...
    • @Radu 这就是这篇文章的全部重点,如果您在旧版本的 Android 上运行,您可以手动调用 onCancelled()。此外,不要针对旧版本(这就是你不能覆盖它的原因)。您的目标应该是最新的 SDK,并且您的最低 SDK 应该是您想要支持的最低版本。
    • 我也遇到了同样的问题,你的回答打开了天堂之门 :) +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多