避免使用 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
    }
  }
}