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