Android FragmentManagerImpl.dispatchResume()恢复无序的片段

Android FragmentManagerImpl.dispatchResume()恢复无序的片段,android,android-fragments,Android,Android Fragments,我在安卓系统中遇到了一个非常奇怪的问题,我不知道为什么会发生这种情况,也不知道如何编写代码。我真的相信这是一个安卓错误 我有一个MainActivity,它包含一个名为main_container的FrameLayout(它的高度和宽度都与父项匹配,因为每个片段应该是向用户“显示”的唯一片段)。在MainActivity中,我添加了如下片段: mFragmentManager.beginTransaction() .replace(R.id.main_container, fra

我在安卓系统中遇到了一个非常奇怪的问题,我不知道为什么会发生这种情况,也不知道如何编写代码。我真的相信这是一个安卓错误

我有一个MainActivity,它包含一个名为main_container的FrameLayout(它的高度和宽度都与父项匹配,因为每个片段应该是向用户“显示”的唯一片段)。在MainActivity中,我添加了如下片段:

mFragmentManager.beginTransaction()
        .replace(R.id.main_container, frag, fragTag)
        .commit();
从那里,用户单击视图后,片段A将添加片段B,如下所示(“frag”和“fragTag”是与上述代码片段不同的值):

从这里开始,片段B将像这样添加片段C(同样,“frag”和“fragTag”的值与前两个片段不同):

所以在这一点上,在backbackback中,我们应该有片段A->片段B->片段C

片段C在用户单击视图时调用MediaPicker。这样做将调用所有片段的onPause方法,应用程序将被置于后台。现在,当用户选择一个图像时,应用程序将恢复,但这里是错误发生的地方。。。它按以下顺序恢复,正如每个片段的onResume方法中的断点所证明的:

片段A->片段C->片段B

这会导致各种各样的问题,因为我的每个片段都注册为MainActivity中的侦听器,以处理后退按钮单击。这种逻辑依赖于顺序是否正确。出于某种原因,它仍然在顶部显示片段C,但onResume显然被称为无序

也许更糟的是。。。您无需单击MediaPicker,只需旋转手机即可更改配置。这显示了重新排序到A->C->B的相同行为,但在本例中,它实际上在顶部显示了错误的片段。上面显示了碎片B

这是不是一个设计点,你不能依靠Android来恢复片段,就像你把它们添加到backbackback中,我应该围绕它编码一样?还是我做错了什么?或者这真的是一个Android bug?到目前为止,我还不是Android开发的新手,但这一点让我感到困惑

编辑:

我已经查明了正在发生的事情,显然这是有意为之。这对我来说似乎很疯狂,我不同意背后的逻辑。我也许可以通过反思来解决这个问题,但我不喜欢这样做。不管怎么说,我还是要解决这个问题

问题在于FragmentManagerImpl跟踪活动片段的方式。它具有跟踪活动片段的功能,当所有内容都暂停时(例如,在我的情况下,我开始打算从media gallery获取照片,因此它将离开我的应用程序),在恢复回我的应用程序时,它会将片段移回ArrayList中的活动状态。听起来不错,嗯

这是我的问题。当从该ArrayList中取出内容时,它们不会移除()该项,而是将其设置为null,然后在出现下一个片段时,有逻辑重用该空“插槽”(github链接中的第1168行)。在我的例子中,在ArrayList中留下一个洞的瞬态片段是DialogFragment。把它放回到我的原始报告中,片段A显示了一个对话框片段。。。单击该对话框Fragment中的某个按钮将显示片段B。单击片段B中的另一个视图将显示片段C。但以下是单击对话框Fragment中的按钮后ArrayList FragmentManagerImpl跟踪的情况:

{FragA,null(用于DialogFragment),FragB}

很明显,在FragB被移动到活动状态后,DialogFragment被移出了活动状态,因此留下了一个洞。现在,我们单击FragB中的视图以打开FragC,ArrayList如下所示:

{FragA,FragC(重用的DialogFragment的插槽),FragB}

我们去了媒体选择器,回来了,瞧,片段恢复的顺序与我最初实例化它们的方式不一致。这对我来说毫无意义,如果你不在操作系统代码中加入断点,你永远也不会明白为什么Android没有按照你告诉它的方式运行。似乎只需对删除的片段执行ArrayList.remove()操作就更容易了,这样就不会留下任何漏洞


就像我说的,我可以通过思考来解决这个问题。。。但我对此持怀疑态度,因为在所有片段中都有这个mIndex变量,它对应于ArrayList(mActive)中它的槽的索引。所以我必须确保它们保持同步。。。现在我需要知道操作系统代码是如何工作的(

这是一个已知的问题。谷歌“android碎片重新排序”,你会得到一整页关于这个主题的链接,包括一些解决方案。

我从搜索中得到的大部分是如何重新排序你的后台。我不希望它重新排序。我实际上已经确定了发生了什么,所以我将用这些信息编辑我的问题。
mFragmentManager.beginTransaction()
        .setCustomAnimations(R.anim.slide_in_right, 0, 0, R.anim.slide_out_right)
        .add(R.id.main_container, frag, fragTag)
        .addToBackStack(null)
        .commit();
mFragmentManager.beginTransaction()
        .setCustomAnimations(R.anim.slide_in_right, 0, 0, R.anim.slide_out_right)
        .add(R.id.main_container, frag, fragTag)
        .addToBackStack(null)
        .commit();