Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java popBackStack()和replace()操作有何不同?_Java_Android_Android Fragments - Fatal编程技术网

Java popBackStack()和replace()操作有何不同?

Java popBackStack()和replace()操作有何不同?,java,android,android-fragments,Java,Android,Android Fragments,在管理片段时,我在应用程序中遇到了一些奇怪的行为,我想知道这样做是否有助于解释为什么会发生这种情况 我有两个片段,我们将它们称为片段A和片段B。我的应用程序的一般流程是,当用户以某种方式与片段A交互时,片段B通过调用fragmentTransaction.replace()(在所有情况下都会发生这种情况)来显示。当我显示片段B时,我将片段A添加到后堆栈中;然后,当用户按下片段B上的后退按钮时,片段A通过从后堆栈弹出再次显示 这很好,但是今天我发现片段B中有一个流,它调用fragmentTrans

在管理片段时,我在应用程序中遇到了一些奇怪的行为,我想知道这样做是否有助于解释为什么会发生这种情况

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

这很好,但是今天我发现片段B中有一个流,它调用
fragmentTransaction.replace()
,将片段B替换为当前位于后堆栈上的片段a的相同实例

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

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

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


编辑以澄清。第二次调用
onCreate()
的情况如下:附加片段a=>替换为片段B,将片段a添加到后堆栈=>使用
popBackStack()弹出片段a
=>再次用片段B替换片段A。

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

replace()
执行两项操作:

  • 从指定的容器(C)中删除当前添加的片段(A)
  • 将新片段(B)添加到同一容器中
  • 这两个操作保存为backbackback记录/事务。请注意,片段A仍处于
    created
    状态,其视图被销毁

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

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

  • 从C中删除B
  • 将A添加到C
  • 在此之后,片段B将被分离,如果您没有保留对它的引用,它将被垃圾收集

    要回答问题的第一部分,没有
    onCreate()
    调用,因为FragmentB仍然处于
    created
    状态。问题第二部分的答案要长一点

    首先,重要的是要理解,实际上并不是将
    片段
    添加到Backstack,而是添加
    片段事务
    。因此,当您认为“替换为片段B,将片段A添加到后堆栈”时,实际上是将整个操作添加到backbackback,即用B替换A。此替换包括两个操作-删除A和添加B

    然后,下一步是弹出包含此替换的事务。所以你不是在弹出片段A,你是在反转“移除A,添加B”,反转的是“移除B,添加A”

    最后一步应该更清楚——FragmentManager不知道B,所以当您在最后一步用B替换A来添加B时,B需要经历它的早期生命周期方法--
    onAttach()
    onCreate()

    下面的代码说明了正在发生的事情

    FragmentManager fm=getFragmentManager();
    FragmentA FragmentA=新的FragmentA();
    FragmentB FragmentB=新的FragmentB();
    // 1. 展示
    fm.beginTransaction()
    .添加(碎片A,R.id.容器)
    .commit();
    // 2. 用B代替A
    //FragmentManager保留对fragmentA的引用;
    //它保持连接和创建;碎片B消失了
    //通过生命周期方法onAttach()、onCreate()
    //等等。
    fm.beginTransaction()
    .更换(碎片B,R.id.容器)
    .addToBackstack(空)
    .commit();
    // 2'. replace()方法的替代方法
    fm.beginTransaction()
    .删除(碎片A)
    .添加(碎片B,R.id.容器)
    .addToBackstack(空)
    .commit();
    // 3. 反面(2);结果-A是可见的
    //发生了什么:
    //1)碎片B已从容器中移除,现在已分离;
    //FragmentManager不再引用它
    //2)碎片A实例放回容器中
    //现在您的backbackback是空的,FragmentManager只知道
    //断章取义
    fm.popbackbackstack();
    // 4. 秀B
    //由于fragmentB被分离,它经历了早期的
    //生命周期方法:onAttach()和onCreate()。
    fm.beginTransaction()
    .更换(碎片B,R.id.容器)
    .addToBackstack(空)
    .commit();
    
    1。我编辑了我的问题,希望能进一步澄清。解决方案的奇怪之处在于,在这两种情况下,片段B似乎都进入分离状态,然后恢复<代码>popBackStack()必须执行不同的操作;我只是好奇那是什么。扩展我的答案,希望这能澄清问题。片段和它们的事务是一个非常复杂的主题。好吧,如果我手动用片段A替换片段B,那么另一个事务记录将添加到后堆栈中。这意味着FragmentManager仍然认为片段B处于分离状态。但是,当我弹出包含片段B的唯一事务时,FragmentManager认为不再附加该片段,因为没有包含它的事务。这是正确的理解吗?另外,感谢您提供的信息丰富的帮助。很高兴能提供帮助!我将试着一句一句地回答。(1) 我显示2'仅作为备选方案,带有eff