8

Android SDK v15 running on a 2.3.6 device.

I'm having an issue where onPostExecute() is still being called when I am calling cancel() within a doInBackground() call.

Here is my code:

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

    return null;
}

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

I am forcing someMethod() to throw an exception to test this out, and instead of onCancelled being called, I always return to onPostExecute(). If I check isCancelled() the returned value is true, so I know that cancel(true) is being executed.

Any ideas?

Sufian
  • 6,405
  • 16
  • 66
  • 120
PolandSpring
  • 2,664
  • 7
  • 26
  • 35

2 Answers2

24

According to the Android API document, onCancelled() is there since API level 3, while onCancelled(Object result) had been added only since API level 11. Because of that, if the platform API level is below 11, onCancelled() will be invoked always while onCancelled(Object) will be invoked always otherwise.

So, if you want to run your code on all API level 3 and above, you need to implement both methods. In order to have the same behavior you may want to store the result in an instance variable so that isCancelled() can be used as shown below:

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
  }
}

By the way, Eric's code does not likely work because the Android API doc says:

Calling the cancel() method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling the cancel() method guarantees that onPostExecute(Object) is never invoked.

theSereneRebel
  • 196
  • 3
  • 16
IdleSun
  • 251
  • 3
  • 5
  • 1
    Good answer but the method name exists a typo. I guess it should be "handleOnCancelled". – TonyQ May 12 '13 at 21:18
  • 1
    Calling the cancel() method guarantees that onPostExecute(Object) is never invoked, thats only right for honeycomb and later for earlier versions refer to @eric answer – Ahmad Dwaik 'Warlock' Sep 26 '13 at 07:40
7

onCancelled is only supported since Android API level 11 (Honeycomb 3.0.x). This means, on an Android 2.3.6 device, it will not be called.

Your best bet is to have this in onPostExecute:

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

If you want to avoid the version check, you can instead do:

protected void onPostExecute(...) {
    if (isCancelled()) {
        customCancelMethod();
    } else {
        // Your normal onPostExecute code
    }
}
protected void onCancelled() {
    customCancelMethod();
}
protected void customCancelMethod() {
    // Your cancel code
}

Hope that helps! :)

Cat
  • 66,919
  • 24
  • 133
  • 141
  • @Radu I've no idea the code you're using or the task you're trying to accomplish. You'd probably be best to start a new question if you've been trying to do something similar to this and are receiving issues. – Cat Jan 18 '13 at 15:06
  • my point is I cannot @ override the onCancelled(SomeType result) and the simple onCancelled(). Also, if I am targetting old Android version, onCancelled() will not be called at all... – Radu Jan 18 '13 at 15:47
  • @Radu That is the entire point of this post, so that you call `onCancelled()` manually if you are running on older versions of Android. Additionally, don't target older versions (that's why you can't override it). Your target should be the latest SDK, and your minimum SDK should be the one that is as low as you want to support. – Cat Jan 18 '13 at 16:48
  • I've had the same problem and your answer opened heavens gate :) +1 – Ahmad Dwaik 'Warlock' Sep 26 '13 at 07:37