AsyncTask Best Practice on how to check if the Activity is still around
After an AsyncTask finishes, I usually do one of the following;
- Call a method on a callback object/interface that I define in the activity and pass to My AsyncTask subclass constructor.
- Provide the AsyncTask with a Handler and call myHandler.sendMess开发者_C百科age() 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?
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.
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
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.
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
}
精彩评论