当前位置: 首页 > 面试题库 >

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

高迪
2023-03-14
问题内容

在管理Fragments时,我的应用程序遇到了一些奇怪的行为,我想知道SO是否可以帮助我们弄清为什么会发生这种情况。

我有两个片段,我们将它们分别称为片段A和片段B。我的应用程序的一般流程是,当用户以某种方式与片段A交互时,通过调用显示片段B
fragmentTransaction.replace()(在所有情况下都会发生)。当显示片段B时,我将片段A添加到后台堆栈中。然后,当用户按下片段B上的“后退”按钮时,通过从后退堆栈弹出,片段A再次显示。

很好,但是今天我发现片段B有一个流,该流调用fragmentTransaction.replace(),用当前在后堆栈上的片段A的相同实例替换片段B。

它本身没有任何问题,但是,当我从片段A返回片段B时,会出现奇怪的行为。如果我调用fragmentTransaction.replace()onCreate()则不会调用片段B
的方法。

但是,如果我从后堆栈中弹出片段A,然后将其替换为片段B,onCreate()则会触发片段B的方法。为什么是这样?

请注意,片段A和片段B的所有实例都是在其主机活动启动时创建的。

编辑进行澄清。onCreate()第二次被调用的情况如下:将Fragment A =>附加为Fragment B,将Fragment A添加到后堆栈=>
pop Fragment A中,使用popBackStack()=>再次将Fragment A替换为FragmentB。


问题答案:

replace() 做两件事:

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

这两个操作被保存为Backstack记录/事务。请注意,片段A保持created状态,并且其视图已损坏。

现在,popBackStack()撤消您添加到BackStack的上一个事务。

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

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

此后,片段B变为detached,如果您不保留对其的引用,它将被垃圾回收。

要回答问题的第一部分,没有任何onCreate()电话,因为FragmentB保持created状态。对问题第二部分的回答要更长一些。

首先,重要的是要了解您实际上并没有添加Fragments到Backstack中FragmentTransactions。所以,当你认为你“与片段B取代,加入片段A到后面栈”,实际上添加这整个操作堆栈中-即
替代 与B. A的这种替换包括2个动作-删除和Add(添加) 。

然后,下一步是弹出包含此替换的事务。因此,您没有弹出FragmentA,而是反转了“删除A,添加B”,反过来就是“删除B,添加A”。

然后最后一步应该更清楚-FragmentManager不会知道B,因此当您在最后一步通过用B替换A来添加它时,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();


 类似资料:
  • 问题内容: 有人可以告诉我中间操作和终端操作有什么区别吗? 操作组合到管道中以处理流。所有操作都是中间操作或终端..means?。 问题答案: Stream支持几种操作,这些操作分为和操作。 此操作之间的区别在于,中间操作是惰性的,而终端操作不是。当您在流上调用中间操作时,该操作不会立即执行。仅在对该流调用终端操作时才执行该命令。在某种程度上,一旦调用了终端操作,便会存储并调用一次中间操作。您可以

  • 本文向大家介绍在history模式中push和replace有什么区别?相关面试题,主要包含被问及在history模式中push和replace有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 push(''):添加一个新的记录到历史堆栈, history.length+1。(一般会用来跳转到一个新页面, 用户点击浏览器的回退按钮可以回到之前的路径。) replace(''):替换掉当前堆栈

  • 我正在使用此代码来清理我的背包到我的主视图: 我很确定这段代码以前是有效的,但现在backstack计数没有改变,没有片段被删除,这会导致内存不足异常,因为while循环一直在运行。 有人知道它是否有问题,或者最新版本的SDK工具中是否有bug吗。我不知道是什么导致了这个问题。

  • 我在下面的manager.popbackbackstack行中遇到此错误。有办法解决这个问题吗?事情发生得很顺利。 致命异常:java.lang.IllegalStateException:在android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2044)在android.support.v4.

  • 本文向大家介绍浅谈java中replace()和replaceAll()的区别,包括了浅谈java中replace()和replaceAll()的区别的使用技巧和注意事项,需要的朋友参考一下 replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是: 1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSeque

  • 本文向大家介绍内核和操作系统之间有什么区别?,包括了内核和操作系统之间有什么区别?的使用技巧和注意事项,需要的朋友参考一下 操作系统 操作系统(OS)是管理计算机硬件资源并充当用户与计算机硬件之间的接口的软件集合。它为计算机程序提供通用服务。操作系统是计算机系统中系统软件的重要组成部分。 核心 内核是操作系统的核心部分,并负责该操作系统的所有主要活动。内核由各种模块组成,它直接与底层硬件交互。它还