Android 避免使用AsyncTask泄漏活动

示例

注意:AsyncTask除了这里描述的内存泄漏之外,还有很多陷阱。因此,请谨慎使用此API,如果您不完全了解其含义,请完全避免使用它。有很多选择(线程,EventBus,RxAndroid等)。

一个常见的错误AsyncTask是捕获对主机Activity(或Fragment)的强烈引用:

class MyActivity extends Activity {
  private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
    //不要这样!内部类隐式保留指向它们的指针
    // 父级,在这种情况下就是活动!
  }
}

这是一个问题,因为AsyncTask它很容易超过父级Activity,例如,如果在任务运行时发生配置更改。

正确的方法是使您的任务成为一个static类,该类不捕获父类,并持有对宿主的弱引用Activity:

class MyActivity extends Activity {
  static class MyTask extends AsyncTask<Void, Void, Void> {
    // 弱引用将仍然允许对活动进行垃圾收集
    private final WeakReference<MyActivity> weakActivity;

    MyTask(MyActivity myActivity) {
     this.weakActivity= new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // 在这里做异步的事情
    }

    @Override
    public void onPostExecute(Void result) {
      // 重新获得对该活动的强烈引用,并进行验证
      // 它仍然存在并处于活动状态。
      MyActivity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // 活动已不再有效,请勿执行任何操作!
        return;
      }

      // 该活动仍然有效,请在此处执行主线程操作
    }
  }
}