4

After an AsyncTask finishes, I usually do one of the following;

  1. Call a method on a callback object/interface that I define in the activity and pass to My AsyncTask subclass constructor.
  2. Provide the AsyncTask with a Handler and call myHandler.sendMessage() when the task is complete.

What I want to ask is what is considered best practice after the AsyncTask is complete. If the user has pressed the home button while the task is processing, the activity is no longer in the foregreound. As soon as the app tries some UI operation, as a response to the task beeing completed, the The OS throws a WindowManager$BadTokenException.

I can of course surround my UI code with a catch for BadTokenException. That seems hacky. Is there any way to tell if the activity is in front?

Glenn Bech
  • 6,103
  • 4
  • 39
  • 56
  • From the error you are getting it seems that you are using the wrong Context, so check that you are passing a valid context where necessary. – Lalit Poptani Aug 03 '11 at 16:34
  • @suri_sahani Cany you specify what you mean by passing a valid context? Passing from where to where? I am passing the Activity as a context to my AsyncTask subclass constructor. – Glenn Bech Aug 03 '11 at 21:26
  • Possible duplicate of [Android AsyncTasks How to Check If activity is still running](https://stackoverflow.com/questions/11189579/android-asynctasks-how-to-check-if-activity-is-still-running) – Audrius Meškauskas Dec 06 '17 at 19:37

4 Answers4

2

Maybe you will not like my answer, but I consider AsyncTask broken (for reasons like this one).

Edit: My initial answer recommended to use an IntentService and broadcast the result. This is as inefficient as sending a letter to yourself.

You can use an AsyncTaskLoader which works around the problems of AsyncTask, but the API of AsyncTaskLoader is far from perfect as well. In particular, you must ensure that loader id is unique, and be aware that results are cached for the id, not for the arguments. Also, the propagation of exception is as broken as with AsyncTask.

A more modern and safer way to approach the problem is to use Guava future.

rds
  • 26,253
  • 19
  • 107
  • 134
  • It is possible just to cancel AsyncTask and it is more or less clear when (onDestroy). [This question](https://stackoverflow.com/questions/11189579/android-asynctasks-how-to-check-if-activity-is-still-running) gives better answers. IntentService is very easy to use one way, but if you need to return the answer also, there is much less code with AsyncTask. – Audrius Meškauskas Dec 06 '17 at 19:41
  • That's an old answer… I've updated it. My recommendation now is to use ListenableFuture. – rds Dec 06 '17 at 21:04
1

It means you are using some where the context that is not appropriate. To clear you doubt about the exception see this Link. Bad Token Exception

Community
  • 1
  • 1
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
  • This seems to be the problem. The Async task can call methods on the activity class even if it's not in the foreground. – Glenn Bech Sep 10 '11 at 19:41
1

You can check if the activity is active or not. I usually make my AsyncTask subclass as static (to avoid memory leak) so I pass a reference of the activity (wrapped on a WeakReference, again to avoid memory leaks).

When onPostExecute is executing I do the necessary checks when using WeakReferences plus call Activity.isFinishing() for the activity, so I can check the activity is not in process of being destroy, to avoid execute UI changes on a dying Activity.

fr4gus
  • 396
  • 7
  • 18
0

Define an object of your activity in your onStart() as a static member -

private static MyActivity mActivity = null;
public void onStart() {
    mActivity = this;
}

public void onDestroy() {
    mActivity = null;
}

Then on your AsyncTask method, do something like:

if (mActivity != null) {
    mActivity.doSomething();  //make sure to use static member
}
Miguel Morales
  • 1,707
  • 10
  • 10
  • Hi. I don't think this will work, did you try it? The activity's onDestroy is not called when the user hits the home button. – Glenn Bech Aug 03 '11 at 21:43
  • Sure, I do this all the time. Although, I generally don't care if they went home. In that case, you should add another static boolean member and have it change onPause() and reset onResume() and do your logic accordingly. – Miguel Morales Aug 04 '11 at 01:39