AsyncTask.onCancelled() не вызывается после отмены (true)

Android SDK v15 работает на устройстве 2.3.6.

У меня возникла проблема где onPostExecute() все еще вызывается, когда я звоню cancel() в пределах doInBackground() вызов.

Вот мой код:

@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) выполняется

Есть идеи?

2 ответа

Согласно документу 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
  }
}

Кстати, код Эрика, скорее всего, не работает, потому что док Android API говорит:

Вызов cancel() метод приведет к onCancelled(Object) вызывается в потоке пользовательского интерфейса после doInBackground(Object[]) возвращается. Вызов метода cancel() гарантирует, что onPostExecute(Object) никогда не вызывается.

onCancelled поддерживается только с уровня API Android 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
}

Надеюсь, это поможет!:)

Другие вопросы по тегам