尽管使用了WeakReference,但仍然引用了被破坏的Activity

时间:2014-10-06 16:10:21

标签: android android-asynctask weak-references illegalstateexception

在活动onCreate中,我首先检查一些远程数据(如果尚未检查),然后更新用户界面:

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

您的私人非静态类InitTask保留对您的活动的引用。 您可以阅读this