4

I am working on an Android app and have encountered an error involving Fragments and FragmentTransactions. I have created an example app to demonstrate the problem. Here is what I am doing:

  1. add Fragment1 to fragmentSpace, without adding to backstack.
  2. replace fragmentSpace with Fragment2, adding to backstack as "beginning".
  3. add Fragment3 to fragmentSpace2 (which is inside of Fragment2), without adding to backstack.
  4. replace fragmentSpace2 with Fragment4, adding to backstack as null.
  5. Call getFragmentManager().popBackStack("beginning", FragmentManager.POP_BACK_STACK_INCLUSIVE); in an attempt to undo all the Transactions, which should bring the user back to seeing only Fragment1.

However, the app crashes on step 5 with this error:

java.lang.IllegalArgumentException: No view found for id 0x7f090004 (me.MitchT.testfragmenttransactions:id/fragmentSpace2) for fragment Fragment3{7f35cb6 #2 id=0x7f090004}
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:886)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:1645)
...

I have found that if I add step 3 to the backstack, step 5 no longer crashes the app and there is no more error. Why?

The problem I have with adding step 3 to the backstack is that I want the user to be able to press the back button after Fragment3 is added and go back to Fragment1. If I add it to the backstack, then when the user presses the back button it removes Fragment3, but Fragment2 is still visible, so they must press the back button again. I am trying to avoid that double-back-button behavior.

I did not feel it was necessary to post the code for every single file in the example app on this question, so instead I created a gist.

So I guess my questions are:

  1. Why do I get this error?
  2. Why don't I get the error after adding step 3 to the backstack?
  3. Is there a better way of "going back to the beginning" or going back two fragments at a time?

Thanks!

Mitch Talmadge
  • 4,638
  • 3
  • 26
  • 44

1 Answers1

2

From what i understand. You have a fragment layout which is the container in activity

Activity hosts Fragment1. Then you replace Fragment 1 by Fragment 2 ( added to back stack.

At this stage clicking back button you will have fragment2 popped and you see the activity which hosts fragment1.

Fragment2 has a framelayout which holds fragment3. Then you have Fragment4 replacing fragment3 which is added to back stack.

Now clicking the button you have getFragmentManager().popBackStack("beginning", FragmentManager.POP_BACK_STACK_INCLUSIVE);. But there is no view with that id.

Just use popBackStack(). Fragment4 --> Fragment2 ( hosting fragment3) --> Fragment1 ( hosted by the activity).

If you want Fragment4 to Activity hosting Fragment1 don't add Fragment4 to the back stack.

Note : In case you want nested fragments you need to use getChildFragmentManager(). https://developer.android.com/about/versions/android-4.2.html

Also note the discussion in the comments sections and the link posted by op Is this the right way to clean-up Fragment back stack when leaving a deeply nested stack?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • In step 2 I add to backstack as "beginning" though: https://gist.github.com/MitchTalmadge/1df0da1828ae168e7314#file-mainactivity-java-L29 Shouldn't it be found from that? – Mitch Talmadge Aug 18 '15 at 06:00
  • @MitchTalmadge but you have fragment4 in the stack. – Raghunandan Aug 18 '15 at 06:05
  • @MitchTalmadge also note that fragment2 is in backstack and fragment3 and 4 is hosted by fragment 2. – Raghunandan Aug 18 '15 at 06:10
  • Thank you, I did a for loop using popBackStack and that solved the issue. I still do not understand how the backstack cannot find "beginning" however. Especially after reading the answer to this question: http://stackoverflow.com/questions/5802141/is-this-the-right-way-to-clean-up-fragment-back-stack-when-leaving-a-deeply-nest It was my understanding that popBackStack(String, int) would essentially do popBackStack() until it reached the transaction with the specified tag. – Mitch Talmadge Aug 18 '15 at 07:16
  • @MitchTalmadge try the same when you have fragment2 replacing fragment1 it does not. also note its nested fragments. still reading the link that you post – Raghunandan Aug 18 '15 at 07:30
  • @MitchTalmadge i tried adding replacing fragment2 with fragment 4. Then the solution in the link you mentioned works like the one you have popBackStack with name. I would also look into the case of nested fragments. – Raghunandan Aug 18 '15 at 07:39
  • @MitchTalmadge in case you need nested fragments you should use `getChildFragmentManager()`. Just try with that keep the same code you had before http://developer.android.com/intl/ko/about/versions/android-4.2.html – Raghunandan Aug 18 '15 at 07:52
  • 1
    Heck yeah! That fixed it! Thanks so much!! I had no idea about getChildFragmentManager(), that makes a lot more sense to me. Thank you! – Mitch Talmadge Aug 18 '15 at 07:58