避免使用 AsyncTask 洩漏活動
需要注意的是 :AsyncTask 與此處描述的記憶體洩漏有很多區別。因此,請謹慎使用此 API,或者如果你不完全瞭解其含義,請完全避免使用此 API。有很多選擇(Thread,EventBus,RxAndroid 等)。
AsyncTask
的一個常見錯誤是捕獲對主機 Activity
(或 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!
}
}
這是一個問題,因為 AsyncTask
可以輕鬆地超過父 Activity
,例如,如果在任務執行時發生配置更改。
正確的方法是讓你的任務成為一個 static
類,它不捕獲父類,並持有對主機 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
}
}
}