Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to destroyed Activity even though WeakReference was used

In activity's onCreate I first check some remote data, if not already checked and then update the 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);
  // ...
}

But, sometimes, my app crashes with this:

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)

The line 1358 is exactly whis one:

private void updateUi(Bundle savedInstanceState) {

So, the WeakReference (pattern) does not save me from AsyncTask returning result to a different MainActivity.

What is the best approach in this case? ServiceIntent?

like image 370
Saran Avatar asked Jan 25 '26 18:01

Saran


1 Answers

The WeakReference will not be set to null until the activity is GC'd, which might be a while after it has been destroyed. After "isFinishing()", add a check for "isDestroyed()". This requires API level 17, so you might need to implement it yourself (a boolean field that is set to false in onDestroy).

Also, for neatness, only use a single call to WeakReference.get(). Theoretically, the GC can run in between the two calls, giving you a NullPointerException.

like image 67
Black Mantha Avatar answered Jan 28 '26 07:01

Black Mantha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!