Ответ 1
replace()
делает 2 вещи:
- Удалить добавленный фрагмент (A) из контейнера (C), который вы указали
- Добавить новый фрагмент (B) в тот же контейнер
Эти 2 операции - это то, что сохраняется как запись/транзакция Backstack. Обратите внимание, что фрагмент A остается в состоянии created
, и его представление уничтожено.
Теперь popBackStack()
отменяет вашу последнюю транзакцию, добавленную в BackStack.
В этом случае это будет 2 шага:
- Удалить B из C
- Добавить A в C
После этого фрагмент B становится detached
, и если вы не сохранили ссылки на него, это будет собирать мусор.
Чтобы ответить на первую часть вашего вопроса, нет вызова onCreate()
, потому что FragmentB остался в состоянии created
. И ответ на вторую часть вопроса немного длиннее.
Во-первых, важно понимать, что вы фактически не добавляете Fragments
в Backstack, вы добавляете FragmentTransactions
. Поэтому, когда вы думаете, что вы "замените фрагментом B, добавив фрагмент A в задний стек", вы фактически добавите всю эту операцию в стопку - это замена A на B. Эта замена состоит из двух действий - удалите A и добавьте B.
Затем следующий шаг - это посылка транзакции, которая содержит эту замену. Таким образом, вы не выходите из FragmentA, вы меняете "удалить A, добавьте B", который обратный - "удалить B, добавить A".
И тогда последний шаг должен быть более ясным - нет B, о котором знает FragmentManager, поэтому, добавив его, заменив A на B на последнем шаге, B должен пройти его ранние методы жизненного цикла - onAttach()
и onCreate()
.
Нижеприведенный код иллюстрирует, что происходит.
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();
// 4. Show B
// Since fragmentB was detached, it goes through its early
// lifecycle methods: onAttach() and onCreate().
fm.beginTransaction()
.replace(fragmentB, R.id.container)
.addToBackstack(null)
.commit();