How do popBackStack() and replace() operations differ?

replace() does 2 things:

  1. Remove currently added fragment (A) from the container (C) you indicated
  2. Add new fragment (B) to the same container

These 2 operations are what is saved as a Backstack record / transaction. Note that fragment A remains in created state, and its view is destroyed.

Now popBackStack() reverses your last transaction that you’ve added to BackStack.

In this case that would be 2 steps:

  1. Remove B from C
  2. Add A to C

After this, fragment B becomes detached, and if you did not keep references to it, it will be garbage collected.

To answer first part of your question, there’s no onCreate() call, because FragmentB remained in created state. And answer to second part of the question is a bit longer.

First, it is important to understand that you don’t actually add Fragments to Backstack, you add FragmentTransactions. So when you think that you “replace with Fragment B, adding Fragment A to the back stack”, you actually add this whole operation to backstack – that is replacement of A with B. This replacement consists of 2 actions – remove A and add B.

Then, next step is popping of the transaction that contains this replacement. So you’re not popping FragmentA, you’re reversing “remove A, add B”, which reversed is “remove B, add A”.

And then final step should be clearer – there’s no B that FragmentManager is aware of, so when you add it by replacing A with B at your last step, B needs to go through its early lifecycle methods – onAttach() and onCreate().

Code below illustrates what is happening.

FragmentManager fm  = getFragmentManager();
FragmentA fragmentA = new FragmentA();
FragmentB fragmentB = new FragmentB();

// 1. Show A
fm.beginTransaction()
  .add(fragmentA, R.id.container)
  .commit();

// 2. Replace A with B
// FragmentManager keeps reference to fragmentA;
// it stays attached and created; fragmentB goes 
// through lifecycle methods onAttach(), onCreate()
// and so on.
fm.beginTransaction()
  .replace(fragmentB, R.id.container)
  .addToBackstack(null)
  .commit();

// 2'. Alternative to replace() method
fm.beginTransaction()
  .remove(fragmentA)
  .add(fragmentB, R.id.container)
  .addToBackstack(null)
  .commit();

// 3. Reverse (2); Result - A is visible
// What happens:
//   1) fragmentB is removed from container, it is detached now;
//      FragmentManager doesn't keep reference to it anymore
//   2) Instance of FragmentA is placed back in the container
// Now your Backstack is empty, FragmentManager is aware only
// of FragmentA instance
fm.popBackStack();

Leave a Comment