在后台堆栈中不是最顶层的片段将恢复

JJD*_*JJD 5 android onresume android-fragments back-stack

鉴于应用程序流程在图形和文本中描述如下所示.

申请流程

  1. 片段1是最低片段,但不是通过设置在backstack中disallowAddToBackStack.
  2. 使用片段2将片段2推入堆栈fragmentTransaction.addToBackStack().
  3. 片段1的新实例被压入堆栈.
  4. 最顶层的片段(片段1)从堆栈中弹出.
  5. 活动2成为前景.
  6. 活动1成为前景.

这是我用来处理片段的通用方法:

private void changeContainerViewTo(int containerViewId,  Fragment fragment, 
                                   Activity activity, String backStackTag) {

    if (fragmentIsAlreadyPresent(containerViewId, fragment, activity)) { return; }
    final FragmentTransaction fragmentTransaction = 
                 activity.getFragmentManager().beginTransaction();
    fragmentTransaction.replace(containerViewId, fragment);
    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    if (backStackTag == null) {
        fragmentTransaction.disallowAddToBackStack();
    } else {
        fragmentTransaction.addToBackStack(backStackTag);
    }
    fragmentTransaction.commit();
}
Run Code Online (Sandbox Code Playgroud)

问题

当活动1在最后一步中恢复时,片段1的最低实例也将恢复.在1返回这个时间点片段nullgetActivity().

  • 为什么堆栈中不是最重要的片段会重新开始?
  • 如果恢复片段是正确的 - 我应该如何处理分离的片段?

小智 1

我不知道这是如何发生的,除非(根据您描述的步骤)您误解了fragmentTransaction.addToBackStack() 的工作原理:它管理哪些事务放置在后台堆栈中,而不是片段中。

来自安卓文档:

通过调用 addToBackStack(),替换事务将保存到返回堆栈,以便用户可以反转事务并通过按“后退”按钮返回上一个片段。

因此,如果您的步骤 2 在代码中看起来像这样:

fragmentTransaction.replace(containerViewId, fragment2);
fragmentTransaction.addToBackStack();
fragmentTransaction.commit();
Run Code Online (Sandbox Code Playgroud)

以及你的第 3 步:

fragmentTransaction.disallowAddToBackStack()//or just no call to addToBackStack - you do not say
fragmentTransaction.replace(containerViewId, newfragment1);
fragmentTransaction.commit();
Run Code Online (Sandbox Code Playgroud)

此时,Fragment2 将从 backstack 中删除,并且您的 backstack 由两个 Fragment1 实例组成。在步骤 4 中,您弹出顶部的 Fragment1,这意味着您现在应该将最底部的 Fragment1 放在顶部。

这解释了为什么如果您返回到活动,它就是恢复的片段。但恐怕这并不是它明显脱离其活动的原因。