replace() 做了两件事:
- 从您指定的容器 (C) 中移除当前添加的片段 (A)
- 将新片段 (B) 添加到同一容器中
这两个操作被保存为 Backstack 记录/事务。请注意,片段 A 仍处于created 状态,并且其视图已被销毁。
现在popBackStack() 撤销了您添加到 BackStack 的最后一个事务。
在这种情况下,这将是 2 个步骤:
- 从 C 中删除 B
- 将 A 添加到 C
在此之后,片段 B 变为 detached,如果您不保留对它的引用,它将被垃圾回收。
要回答您问题的第一部分,没有 onCreate() 电话,因为 FragmentB 仍处于 created 状态。问题的第二部分的答案更长一些。
首先,重要的是要了解您实际上并未将Fragments 添加到Backstack,而是添加了FragmentTransactions。因此,当您认为“用片段 B 替换,将片段 A 添加到后台堆栈”时,您实际上将整个操作添加到后台堆栈 - 即 用 B 替换 A。这个替换包括 2操作 - 删除 A 并添加 B。
然后,下一步是弹出包含此替换的事务。所以你不是在弹出 FragmentA,你是在反转“删除 A,添加 B”,反转是“删除 B,添加 A”。
然后最后一步应该更清楚 - FragmentManager 不知道 B,所以当您在最后一步通过用 B 替换 A 来添加它时,B 需要通过其早期生命周期方法 - onAttach() 和 @ 987654330@.
下面的代码说明了正在发生的事情。
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();