26

I have a problem about removing a specific fragment from back stack.My scenario is like this.Fragment-1 is replaced with Fragment-2 and then Fragment-2 is replaced with Fragment-3.

Calling order; Fragment-1-->Fragment-2-->Fragment-3.

When Fragment-3 is on the screen and then back button is clicked, i want to go

Fragment-1.That means i want to delete Fragment-2 from back stack.

How to do this ?

nihasmata
  • 652
  • 1
  • 8
  • 28

5 Answers5

28

In the backstack you don't have Fragments, but FragmentTransactions. When you popBackStack() the transaction is applied again, but backward. This means that (assuming you addToBackStackTrace(null) every time) in your backstack you have

1->2
2->3

If you don't add the second transaction to the backstack the result is that your backstack is just

1->2

and so pressing the back button will cause the execution of 2->1, which leads to an error due to the fragment 2 not being there (you are on fragment 3).
The easiest solution is to pop the backstack before going from 2 to 3

//from fragment-2:
getFragmentManager().popBackStack();
getFragmentManager().beginTransaction()
   .replace(R.id.container, fragment3)
   .addToBackStack(null)
   .commit();

What I'm doing here is these: from fragment 2 I go back to fragment 1 and then straight to fragment 3. This way the back button will bring me again from 3 to 1.

Ilario
  • 662
  • 11
  • 23
  • it is not the exact solution i want.I must add fragment-2 to the back stack when going to fragment-3.In the fragment-3 depending on a condition i want to remove fragment-2 from backstack without any action then back button is clicked,just want to go fragment-1 – nihasmata Jul 04 '15 at 01:12
  • 1
    @sahin Ok, then it's not a viable option... Maybe you could try with [popBackStack (int id, int flags)](http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack%28int,%20int%29), but I did not try it, I don't know about the behaviour with animations... – Ilario Jul 05 '15 at 01:44
  • 3
    When you poping backstack before going from 2 to 3 system trying to show fragment 1. Each time when you poping fragment number N it tries to show fragment number (N-1). And if you forcing to go to fragment 3 you'll get NPE during onCreateView of 1 fragment... – Yazon2006 Jul 22 '16 at 05:22
  • @llario , thanks for your answer that save my issue. – Morton May 09 '17 at 08:22
  • The app is crashing when using this method when using androidx appcompat library. An exception is thrown "Fatal Exception: java.lang.IllegalStateException Restarter must be created only during owner's initialization stage" because the current state of the lifecycle is not Initialized. Check class SavedStateRegistryController and search for this error. – sunlover3 Nov 13 '19 at 10:15
  • 1
    @sunlover3 I used this method on Lollipop, many things might have changed in four and a half years... There is at least one question about the problem, https://stackoverflow.com/questions/56539251/backstack-management-restarter-must-be-created-only-during-owners-initializat I'm not in andorid development anymore, can't help you much more, sorry – Ilario Nov 13 '19 at 11:18
  • @Ilario Don't worry. And yes, Android developed a lot in the last years. My answer just explained the current behaviour. Thanks! Good luck in your career! :) – sunlover3 Nov 14 '19 at 08:52
10

I had a very similar scenario to yours, my solution was just checking the amount of backStack transactions that I had.

If the transactions where more than 0 then I would simply pop it right away so it would skip it when pressing back.

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
        getSupportFragmentManager().popBackStackImmediate();
}
...
fragmentTransaction.replace(R.id.main_fragment, newFrag, MAIN_FRAGMENT_TAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.commit();

This would successfully:

  • A -> B (back pressed) -> back to A

  • A -> B -> C (back pressed) -> back to A

The only downside that I see is that there is a quick flash where fragment A is displayed before going to fragment C.

Iv4n
  • 101
  • 1
  • 3
  • Calling just `.popStack()` as others suggested - in my situation - caused the view to automatically revert to A after it went to C *- before back button was pressed*. The `popBackStackImmediate()` listed here is what made the difference in my case, and I now have back button from C going back to A - none of the other answers I ran across had mentioned it. Thanks! – Gene Bo Feb 02 '17 at 02:39
  • Please specify where to write this code? I mean which fragment. – Sreekanth Karumanaghat Aug 29 '17 at 10:05
6

If you are adding/launching all three fragments in the same activity, instead of the add(), use replace() (replace Fragment2 with Fragment3). The replace method removes the current fragment from backstack before adding the new one. If you are launching Fragment3 from a different activity, and thus you can't use replace(), remove Fragment2 from backstack before starting the new activity (which adds Fragment3):

// in Fragment2, before adding Fragment3:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
               .remove(this) // "this" refers to current instance of Fragment2
               .commit();
fragmentManager.popBackStack();
// now go ahead and launch (add) fragment3
// if fragment3 is launched from a different activity, 
// start that activity instead
fragmentManager.beginTransaction()
               .add(R.id.a_container_view_in_activity, new Fragment3(),
                    Fargment3.FRAGMENT3_ID)
               .commit();
Javad
  • 5,755
  • 4
  • 41
  • 51
4

Code for Fragment A -> Fragment B:

Add Fragment A in BackStack of Fragments

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Code for Fragment B -> Fragment C:

Do not Add Fragment B in BackStack of Fragments

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentC());
fragmentTransaction.commit();

It will works in this way: A -> B -> C and while returning C-> A as you excepted.

Hope it will help you.

Lasse
  • 597
  • 2
  • 10
  • 33
Hiren Patel
  • 52,124
  • 21
  • 173
  • 151
3
   for (int i = 0; i < mFragmentManager.getBackStackEntryCount(); i++) {
        currentFragment = mFragmentManager.getFragments().get(i);
        if (!(currentFragment instanceof ParticularFragment))
            mFragmentManager.popBackStack();
        else
            break;
    }
Rudee
  • 29
  • 2