Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment already added IllegalStateException

I use this method on my container Activity to show a BFrag

public void showBFrag()
{
    // Start a new FragmentTransaction
    FragmentTransaction fragmentTransaction = mFragmentMgr.beginTransaction();

    if(mBFrag.isAdded())
    {
        Log.d(LOG_TAG, "Show() BFrag");
        fragmentTransaction.show(mBFrag);   
    }
    else
    {
        Log.d(LOG_TAG, "Replacing AFrag -> BFrag");
        fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);
    }

    // Keep the transaction in the back stack so it will be reversed when backbutton is pressed
    fragmentTransaction.addToBackStack(null);

    // Commit transaction
    fragmentTransaction.commit();        
}

I call it from my container Activity; for the first time:

  • gets into the else statement and mBFrag replace mAFrag.

Then I press the back button:

  • and the operation is reversed (mAFrag is shown but.. does mBFrag is removed?).

Then I go forward again by calling showBFrag() from the same Activity:

  • and it gets AGAIN into the else statement. (so I can deduce that mBFrag is NOT ADDED)
  • but I got a Fragment already added IllegalStateException... (so why it didn't get into the if statement instead?)

So:

  1. Why is the isAdded() method not returning TRUE if I'm getting a Fragment already added IllegalStateException??
  2. Does popBackStack operation completely remove previously added fragments?
  3. What behaviour am I misunderstanding?

EDIT: Here is the complete info of the exception.

06-07 12:08:32.730: ERROR/AndroidRuntime(8576): java.lang.IllegalStateException: Fragment already added: BFrag{40b28158 id=0x7f0c0085}
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.doAddOp(BackStackRecord.java:322)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:360)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at android.app.BackStackRecord.replace(BackStackRecord.java:352)
06-07 12:08:32.730: ERROR/AndroidRuntime(8576):     at myPackageName.containerActivity.showBFrag() // This line: "fragmentTransaction.replace(R.id.operation_fragments_frame, mBFrag);"
like image 399
Axel M. Garcia Avatar asked Jun 06 '11 10:06

Axel M. Garcia


3 Answers

In the end my workaround was to execute remove() of the previous fragment and add() the new one. Although that's what replace() method was meant to do.

But I am still guessing why replace() method didn't work properly in this case. It is really weird and I want to discard that it is because I am misunderstanding something or doing something wrong.

like image 155
Axel M. Garcia Avatar answered Nov 17 '22 05:11

Axel M. Garcia


If the state of the activity has already been saved its no longer safe to call commit. You must call commitAllowingStateLoss() instead. Hope this helps!

Edit: ok I've taken a closer look at your issue, problem is you are trying to add a fragment that has already been added. Even if you use replace or remove calls you can't do this. Only work around I have found is to create a new instance of a fragment and add it every time. Once you remove or replace a fragment it is best to drop all of your references to it so the GC can take care of it.

like image 12
Nathan Schwermann Avatar answered Nov 17 '22 04:11

Nathan Schwermann


Probably not related to this issue directly, but I've also noticed that setting a transition to the FragmentTransaction will cause an IllegalStateException, while not setting a transition will not.

Here's the bug for this issue: http://code.google.com/p/android/issues/detail?id=25598

like image 8
Johan Paul Avatar answered Nov 17 '22 04:11

Johan Paul