片段方法:attach(),detach(),remove(),replace(),popBackStack()

35
我对这些函数及其目的感到非常困惑。根据我的观察,使用replace()会用新的片段替换现有的片段。我们可以使用addToBackStack(null)将该片段放入返回堆栈中,以便可以返回到先前显示的片段。现在当添加(或替换)片段时,片段的onAttach()onCreate()等方法按顺序调用。

现在,当我们从活动中调用remove()来删除片段时,哪些片段函数被调用以及它们的顺序是什么?

attach()detach()是什么? detach()是否会删除片段?当使用这两个attach()detach()时,片段的哪些函数被调用以及顺序是什么?

此外,popBackStack() 会发生什么?也就是说,当我们在活动中针对片段使用popBackStack() 时,会调用哪些函数?

并且,onDestroy() 会在什么时候被调用?

谢谢。

3个回答

24
现在,当我们从活动中调用remove()方法来移除片段时,片段的哪些功能被调用,以及按照什么顺序调用?
请查看http://developer.android.com/reference/android/app/Fragment.html
顺序是:onPause()onStop()onDestroyView()onDestroy()onDetach() attach()和detach()分别将Fragment与Activity关联或分离。当附加Fragment时,会调用onAttach()生命周期方法;当分离Fragment时,在Fragment中调用onDetach()生命周期方法。有关更多信息,请参见上面的链接。detach()是否会删除片段?
如果Fragment没有被销毁,那么在从Activity中使用popBackStack()弹出Fragment时,会调用onStart()和onResume()方法。如果Fragment之前已被销毁,则从onAttach()开始调用生命周期方法。这与按下Activities上的返回按钮相同。

2
在调用popBackStack()方法时,会触发onStart()和onResume()方法的调用。这是怎么可能的???我们正在弹出片段,而不是添加它。 - Vikram Gupta
1
当您弹出后退栈时,意味着您删除当前片段,并将其替换为上一个片段,其中上一个片段存储在后退栈中。 - Adam Monos
@vickey 在使用 popBackStack() 方法时,onStart() 和 onResume() 方法没有被调用。我正在寻找解决方案,因为我需要调用一个 Web 服务。有什么建议吗? - Rishabh Srivastava
1
@Tapirboy,实际上已经过去2年了,所以我已经找到了一种方法:D - Rishabh Srivastava
10
关于 attach() 和 detach() 的回答是不正确的。 调用 detach() 会使片段仍然附加到活动上,因此不会调用 onDetach(),但是它会分离其视图层次结构,依次调用 onPause()onStop()onDestroyView()。 调用 attach() 要求该片段处于分离的视图状态,并将其恢复到正常状态,依次调用:onCreateView()onActivityCreated()onStart()onResume() - BladeCoder
显示剩余3条评论

13

关于popBackStack()的一点说明。它不会弹出一个片段,而是弹出一个片段事务。因此,无论最后一个片段事务是什么,都将被撤消。如果您正在显示FragmentA并且您的事务是:

fragmentTransaction.replace(R.id.your_layout, fragmentB);
fragmentTransaction.addToBackStack(null);

它将用FragmentB替换FragmentA,并将该事务(而非片段)添加到后退堆栈中。如果您按下返回按钮,则弹出后退堆栈并获取该事务,该事务为“用FragmentB替换此FragmentA”。然后反转该事务。向后,指令是将当前片段替换为FragmentA。如果原始的FragmentA仍然存在,则使用该片段。如果已被销毁,则创建一个新的。


4
假设通过以下步骤向容器添加了片段A和片段B:

假设通过以下步骤向容器添加了片段A和片段B:

1. Added fragment A =>  .replace(R.id.container, fragmentA) => addToBackStack(null)
2. Added fragment B =>  .replace(R.id.container, fragmentB) => addToBackStack(null)
3. Removed fragment B => fragmentManager.popBackStack();

当调用fm.popBackStack()时的回调函数:

FragmentB: onPause()
FragmentB: onStop()
FragmentB: onDestroy()
FragmentB: onDetach()
FragmentA: onCreateView()
FragmentA: onViewCreated()
FragmentA: onActivityCreated()
FragmentA: onStart()
FragmentA: onResume()

解释:为什么使用popBackStack()删除和销毁片段B时,片段A的视图会被再次创建并恢复?

答案:当你添加片段B时,使用了replace()和addToBackStack()方法,因此所有的片段都从容器中移除了,然后将片段B添加到容器中。同时,这个事务也被记录在返回堆栈中。所以,当调用fm.popBackStack()方法时,首先从返回堆栈中弹出该事务,因此操作被还原,片段B从容器中移除并被销毁。而其他所有片段则被添加,对于我们的情况,片段A的视图被添加到容器中。请注意,片段A的onAttach()和onCreate()方法不会被调用,因为它已经在之前被创建并附加到MainActivity上。

按下片段B的返回键也会做同样的事情:

If you press the back button, it calls fm.popBackStack() and pops the transaction.

但是当你返回或替换时,它不会销毁片段,对吗?我以为它只是在后台暂停了,不是吗? - Burkely91
不,当您按下返回按钮时,它会被销毁。 - Richa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接