【问题标题】:Reference to destroyed Activity even though WeakReference was used即使使用了 WeakReference 也对已销毁的 Activity 的引用
【发布时间】:2014-11-30 22:54:10
【问题描述】:

在活动的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?

【问题讨论】:

  • 弱引用不会阻止任何东西被GCed,但它与这种情况无关。 Activity 被销毁的事实与它的生命周期有关。您可能希望绑定到活动中的服务,或者如果活动被破坏,则简单地忽略异步任务的结果。当您的活动暂停时,可能在 AsyncTask 上调用 cancel
  • 可能与这里的问题相同:stackoverflow.com/questions/15207305/…

标签: android android-asynctask weak-references illegalstateexception


【解决方案1】:

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

另外,为了简洁起见,只使用一次对 WeakReference.get() 的调用。理论上,GC 可以在两次调用之间运行,给你一个 NullPointerException。

【讨论】:

  • 您关于单次调用WeakReference.get() 的观点是绝对正确的。必须get() 引用的对象,然后直接使用它。任何后续使用WeakReference 都是对NullPointerException 的邀请。
【解决方案2】:

您的私有非静态类 InitTask 持有对您活动的引用。 你可以阅读this 了解它。

【讨论】:

  • 404... 这就是为什么链接到第 3 方网站不如在此处粘贴相同信息更受鼓励的原因。
  • @Saran,对不起,请重试,我已更改文章链接。
猜你喜欢
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2014-12-02
  • 1970-01-01
  • 2013-09-15
  • 1970-01-01
  • 2012-04-15
相关资源
最近更新 更多