popBackStack()和replace()操作如何区别?

在pipe理碎片时,我在应用程序中遇到了一些奇怪的行为,我想知道是否可以帮助解释为什么发生这种情况。

我有两个片段,我们将它们称为片段A和片段B.我的应用程序的一般stream程是,当用户以某种方式与片段A交互时,通过调用fragmentTransaction.replace()显示片段B(这发生在所有情况)。 当我显示片段B时,我将片段A添加到后端堆栈; 然后,当用户按下片段B上的后退button时,片段A通过从后退栈中popup而再次显示。

这一切都很好,但今天我发现有一个来自片段B的stream,它调用fragmentTransaction.replace() ,用片段A的相同实例replace片段B,片段A当前位于后端堆栈中。

本身并没有什么错,但是当我从片段A返回到片段B时出现了奇怪的行为。如果我调用fragmentTransaction.replace() ,片段B的onCreate()方法不会被调用。

但是,如果我从后端堆栈中popup碎片A,然后用碎片Breplace它,则会激发碎片B的onCreate()方法。 为什么是这样?

请注意,Fragment A和Fragment B的所有实例都是在其主机Activity启动时创build的。

编辑澄清。 第二次调用onCreate()的情况如下:附加Fragment A =>用Fragment Breplace,将Fragment Ajoin到后面的栈中=> pop使用popBackStack() => Fragment A再次用碎片BreplaceFragment A 。

Solutions Collecting From Web of "popBackStack()和replace()操作如何区别?"

replace()做了两件事情:

  1. 从您指定的容器(C)中删除当前添加的片段(A)
  2. 添加新的片段(B)到相同的容器

这2个操作是作为Backstacklogging/事务保存的。 请注意,片段A保持created状态,其视图被破坏。

现在popBackStack()您添加到BackStack的最后一个事务。

在这种情况下,这将是2个步骤:

  1. 从C中删除B.
  2. 将A添加到C

在此之后,片段B变得detached ,如果你不参考,它将被垃圾收集。

要回答你的问题的第一部分,没有onCreate()调用,因为FragmentB保持created状态。 而问题的第二部分的答案是有点长。

首先,理解你实际上并没有将Fragments添加到Backstack中,这是很重要的,你需要添加FragmentTransactions 。 所以当你认为你“用碎片Breplace,把碎片A添加到后端堆栈”时,你实际上把这个整个操作添加到了后端堆栈 – 即用BreplaceA.这个replace包括2个操作 – 删除A和添加B 。

然后,下一步是popup包含此replace的事务。 所以你没有popupFragmentA,你正在倒转“删除A,添加B”,反过来就是“删除B,加A”。

然后最后一步应该更清楚了–FragmentManager没有意识到的B,所以当你在最后一步用BreplaceA时,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(); 

这可能是因为片段pipe理器重复使用片段实例而不是重新创build它。 如果片段B onCreate()的代码需要在显示片段时执行,那么请使用另一种方法(如onResume()移动代码。