A word of caution: AsyncTask has many gotcha's apart from the memory leak described here. So be careful with this API, or avoid it altogether if you don't fully understand the implications. There are many alternatives (Thread, EventBus, RxAndroid, etc).
One common mistake with AsyncTask
is to capture a strong reference to the host Activity
(or Fragment
):
class MyActivity extends Activity {
private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
// Don't do this! Inner classes implicitly keep a pointer to their
// parent, which in this case is the Activity!
}
}
This is a problem because AsyncTask
can easily outlive the parent Activity
, for example if a configuration change happens while the task is running.
The right way to do this is to make your task a static
class, which does not capture the parent, and holding a weak reference to the host Activity
:
class MyActivity extends Activity {
static class MyTask extends AsyncTask<Void, Void, Void> {
// Weak references will still allow the Activity to be garbage-collected
private final WeakReference<MyActivity> weakActivity;
MyTask(MyActivity myActivity) {
this.weakActivity = new WeakReference<>(myActivity);
}
@Override
public Void doInBackground(Void... params) {
// do async stuff here
}
@Override
public void onPostExecute(Void result) {
// Re-acquire a strong reference to the activity, and verify
// that it still exists and is active.
MyActivity activity = weakActivity.get();
if (activity == null
|| activity.isFinishing()
|| activity.isDestroyed()) {
// activity is no longer valid, don't do anything!
return;
}
// The activity is still valid, do main-thread stuff here
}
}
}