5

The correct behavior I'd like to have is:

Fragment A -> Fragment B -> Fragment C -> Fragment A

What I currently do:

  1. When I want to go back from B to A, I use popBackStack() still here everything goes well.
  2. When I want to go from B to C I remove B and add C. (number of Fragments 2, number of backStackEntryCount 3, same for replace).
  3. When I want to go back from C to A, I can use popBackStack() but the BackStackEntryCount will still contain the entry for B.

I really need the backStackEntryCount to be the same as the fragments contained in the manager.

Anyone know what I am doing wrong?

My code:

        Fragment fragment1 = fragmentManager.findFragmentByTag("NavigationFragment_");
    if (fragment1 != null) {
        fragmentManager.beginTransaction()
                .setTransition(TRANSIT_FRAGMENT_FADE)
                .remove(fragment1)
                .commit();

    }

    fragmentManager.beginTransaction()
            .addToBackStack(backstack)
            .setTransition(TRANSIT_FRAGMENT_OPEN)
            //.remove(getFragmentManager().findFragmentByTag(NavigationFragment_.class.getSimpleName()))
            .add(R.id.fragmentContainer, fragment, fragment.getClass().getSimpleName())
            .commit();

I have been searching for a solution for a while without results, so please do not mark this a duplicate.

Thanks in advance.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Jonathan I
  • 240
  • 1
  • 4
  • 18
  • Can you provide an SSCCE? – m0skit0 Nov 06 '18 at 15:07
  • What does it mean? :') – Jonathan I Nov 06 '18 at 15:09
  • http://sscce.org/ – m0skit0 Nov 06 '18 at 15:11
  • Ok, I am doing one now – Jonathan I Nov 06 '18 at 15:13
  • If you want to replace the fragment in a container you should use `replace` instead of `remove` and `add`. Good answer here https://stackoverflow.com/a/18634392/1729054 – Luca Corradi Nov 06 '18 at 15:13
  • 1
    @LucaCorradi As I wrote, it does not have any effect and fix to my problem even because it is the same according to the docs: https://developer.android.com/reference/android/support/v4/app/FragmentTransaction#replace – Jonathan I Nov 06 '18 at 15:16
  • @m0skit0 this is the logic:https://github.com/JonathanImperato/test/tree/master , sorry for the late answer – Jonathan I Nov 06 '18 at 15:47
  • SSCCE, here, is known as MCVE: [mcve]. – Phantômaxx Nov 06 '18 at 16:16
  • @KlingKlang Right, but that SO post lacks a very important point: "By identifying more clearly where the problem occurs, you have just made an important step toward solving it. The process that highlights where a problem originates can, in itself, help to solve it. You might look more closely at the part cut out, and in doing so, spot the problem. Even if you cannot see why the problem occurs, you have still made an important step: identifying (at least part) of the code involved". – m0skit0 Nov 06 '18 at 17:14
  • @JonathanI `BaseFragment#showFragment` always tries to remove `FragmentB`. – m0skit0 Nov 06 '18 at 17:25
  • 1
    @m0skit0 I usually make a control, if FragmentB does not exist in the fragment manager then nothing will be removed, I forgot to add it, fixing it now in the project sample – Jonathan I Nov 06 '18 at 17:55

2 Answers2

1

If you come here because you call popBackStack() but getBackStackEntryCount() doesn't seem to update, then you might want to try popBackStackImmediate() instead.

popBackStack() is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop.

Johan Franzén
  • 2,355
  • 1
  • 17
  • 15
0

The FragmentManager's back stack is only updated in two cases:

  1. You commit a FragmentTransaction using addToBackStack()
  2. You call popBackStack()

No other operation affects the back stack - additional FragmentTransactions without addToBackStack() only change the current state and do not affect what happens when you call popBackStack(), etc.

If you want your stack to go from A to A -> B, you'd use a FragmentTransaction with addToBackStack (and generally, a replace operation):

fragmentManager.beginTransaction()
    .replace(R.id.fragmentContainer, fragmentB)
    .addToBackStack("b")
    .commit();

Then, you want your back stack to A -> B to A -> C, you'd need to do two operations:

// First pop B
fragmentManager.popBackStack("b", FragmentManager.POP_BACK_STACK_INCLUSIVE)
// Then addToBackStack C
fragmentManager.beginTransaction()
    .replace(R.id.fragmentContainer, fragmentC)
    .addToBackStack("c")
    .commit();

This ensures that your FragmentB is removed from the stack before adding FragmentC to the back stack.

Similarly, if you want to then remove FragmentC and go back to FragmentA, you'd just pop it from the back stack:

// Pop C, returning back to A
fragmentManager.popBackStack("c", FragmentManager.POP_BACK_STACK_INCLUSIVE)

Note: it is never a good idea to mix back stack FragmentTransactions and regular FragmentTransactions in the same FragmentManager since popBackStack() does not take into account the current state of the FragmentManager, but instead just blindly reverses the FragmentTransaction on the back stack (i.e., the last FragmentTransaction with addToBackStack().

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443