android - 引用已销毁的 Activity,即使使用了 WeakReference

标签 android android-asynctask weak-references illegalstateexception

在 Activity 的 onCreate 中,我首先检查一些远程数据,如果尚未检查,然后更新 UI:

private static WeakReference<MainActivity> wrActivity = null;

protected void onCreate(final Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  wrActivity = new WeakReference<MainActivity>(this);
  // ...
}

private class InitTask extends AsyncTask<Object, Void, Bundle> {
  @Override
  protected Bundle doInBackground(Object... params) {
    // checking some (network) stuff

    return (Bundle) params[0];
  }

  @Override
  protected void onPostExecute(final Bundle savedInstanceState) {
    if (wrActivity.get() == null || wrActivity.get().isFinishing()) {
      return;
    }

    updateUi(savedInstanceState);
  }
}

private void updateUi(Bundle savedInstanceState) {
  Log.d(getClass().getSimpleName(), "updateUi()");

  if (savedInstanceState == null) {
    resetActionBar();
  }

  initPagerAndTabs(savedInstanceState);

  // ...
}

private void initPagerAndTabs(Bundle savedInstanceState) {
  Log.d(getClass().getSimpleName(), "initPagerAndTabs()");
  mTabNames = getResources().getStringArray(R.array.tabs);

  mAdapter = new FragmentAdapter(getSupportFragmentManager());
  mPager = (ViewPager) findViewById(R.id.pager);
  mPager.setAdapter(mAdapter);
  mPager.setOnPageChangeListener(mAdapter);
  // ...
}

但是,有时,我的应用程序会因此而崩溃:

java.lang.IllegalStateException: Activity has been destroyed
  at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1376)
  at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
  at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
  at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139)
  at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:415)
  at com.mypackage.MainActivity.access$9(MainActivity.java:1358)
  at com.mypackage.MainActivity$InitTask.onPostExecute(MainActivity.java:1)

第 1358 行恰好是一行:

private void updateUi(Bundle savedInstanceState) {

因此,WeakReference(模式)不会让我免于 AsyncTask 将结果返回到不同的 MainActivity。

在这种情况下最好的方法是什么? ServiceIntent?

最佳答案

在 Activity 被 GC 之前,WeakReference 不会被设置为 null,这可能是在它被销毁之后的一段时间。在“isFinishing()”之后,添加对“isDestroyed()”的检查。这需要 API 级别 17,因此您可能需要自己实现它(在 onDestroy 中设置为 false 的 bool 字段)。

另外,为了整洁起见,只调用一次 WeakReference.get()。理论上,GC 可以在两次调用之间运行,从而为您提供 NullPointerException。

关于android - 引用已销毁的 Activity,即使使用了 WeakReference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26220322/

相关文章:

Java解密RSA加密数据ArrayIndexOutOfBoundsException : too much data for RSA block

android - 是否可以在 onPostExecute 中启动一个 Activity ?

ios - 弱引用被清零,但对象尚未被释放

swift - 如何在快速闭包中实现单向引用

android - 在 Eclipse 中获取 URL 失败

android - Zbar 集成到 Android 应用程序中

java - 在AsyncTask中添加Marker到map api v2

java - 如何中途停止异步任务

java - JVM - WeakReferences 是否在次要 GC 中收集?

java - Java中的switch语句可以使用 "view"作为参数吗?