FragmentTransaction::replace() with or without addToBackStack()

lannyf picture lannyf · Nov 3, 2015 · Viewed 9k times · Source

Having a flow to add fragment and later replace() fragment. All fragment are dynamically added, but not all call addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(R.id.frgment_holder, frgmtA, frgmtA.NAME)
    .commit();

and in somewhere it could add another, like:

getSupportFragmentManager().beginTransaction()
    .replace(R.id.frgment_holder, frgmtB)
    .addToBackStack(frgmtB.NAME)
    .commit();

the replace() with the frgmtB will remove the frgmtA from the container R.id.frgment_holder. if press back button at this state, it will pop the frgmtB. But will it recreate the frgmtA even if it did not call addToBackStack() when did the adding?

if in the flow of adding fragment into same container with a serials mixed add() and replace() calls, and someone call addToBackStack() but someone do not, how would the back button behavior?

EDIT: after

getSupportFragmentManager().beginTransaction()
        .replace(R.id.frgment_holder, frgmtB)
        .addToBackStack(frgmtB.NAME)
        .commit();

will the

getSupportFragmentManager().findFragmentByTag(frgmtA.NAME);

still find the the frgmtA? what if when add frgmtA also called addToBackStack();

The doc says "This first searches through fragments that are currently added to the manager's activity; if no such fragment is found, then all fragments currently on the back stack are searched."

The case would be

  1. adding frgmtA; not call add to stack; UI state changed here;

(what if the frgmtA is not dynamically added by add(), but sepcified in layout file with class="frgmtA"?).

  1. replace() with frgmtB; addToStack();

  2. replace() with frgmtC; addToStack();

then if the stackTop is frgmtC, would like the back button press to bring back the first frgmtA with its last UI state.

Answer

lannyf picture lannyf · Nov 6, 2015

1.

.add(R.id.frgment_holder, frgmtA, frgmtA.NAME)
            .commit();
.replace(R.id.frgment_holder, frgmtB, frgmtB.NAME)
        .addToBackStack(frgmtB.NAME)
        .commit();`

the replace will remove the frgmtA from the the holder and its onDestroyView will be called (but since it is referenced in the backstack’s transaction data, frgmtA is NOT destroyed). And the frgmtB will be added to the holder. Since the frgmtA is not destroyed, the

getSupportFragmentManager().findFragmentByTag(frgmtA.NAME); 

will find it.

after then, press on back button, it will pop the top transaction from the backStack, then reversing the transaction. i.e. remove frgmtB from the holder and add frgmtA back to the holder. Since there is no more reference to frgmtB its onDestroy is called.

2. in the case of

add frgmtA;
replace() with frgmtB; addToStack();
replace() with frgmtC; addToStack(); 

If want to back press to jump to frgmtA, need to override onBackPressed(), in it do

popBackStack(frgmtB.NAME, POP_BACK_STACK_INCLUSIVE), 

which will toss out the transaction in the stack above stack entry named frgmtB.NAME and do reverse the transaction on it, which will add back the frgmtA in the holder.