5

给定的应用程序流程显示在图形和文字描述如下。

申请流程

  1. 通过设置,片段 1 是最低的片段,但不在后台堆栈中disallowAddToBackStack
  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();
}

问题

当活动 1 在最后一步恢复时,片段 1 的最低实例也恢复。此时片段 1 重新null打开getActivity()

问题

  • 为什么恢复堆栈中不是最顶部的片段?
  • 如果恢复片段是正确的 - 我应该如何处理分离的片段?
4

3 回答 3

2

当一个Activity没有显示 UI 然后来显示 UI 时,FragmentManager关联的所有片段都将消失,您需要恢复其状态。

正如文档所说:

在很多情况下,一个片段可能大部分被拆除(例如当放置在没有显示 UI 的后台堆栈时),但它的状态不会被保存,直到它拥有的 Activity 实际需要保存它的状态。

在您的Activity onSaveInstanceStateandonRestoreInstanceState中,尝试保存您的Fragment引用,然后使用以下内容恢复它们:

public void onSaveInstanceState(Bundle outState){
    getFragmentManager().putFragment(outState,"myfragment", myfragment);
}
public void onRetoreInstanceState(Bundle inState){
    myFragment = getFragmentManager().getFragment(inState, "myfragment");
}

试试这个,祝你好运!:-)

于 2013-05-23T21:51:51.797 回答
1

Android 操作系统可以并且将在它认为合适的时候创建和销毁片段。当您启动 Activity 2 并返回到 Activity 1 时,可能会发生这种情况。我会确认它不是主动显示的片段。可能发生的情况是,您看到它在执行片段 2 的创建步骤之前为片段 1 执行了一些创建步骤。

至于处理分离的片段,你应该看看这个页面。它的要点是您应该只在某些片段函数中使用 getActivity(基于片段生命周期)。这可能意味着您必须将一些逻辑移至其他功能。

于 2013-05-24T14:36:52.663 回答
1

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

来自安卓文档:

通过调用 addToBackStack(),替换事务被保存到后退堆栈,因此用户可以通过按“后退”按钮来撤销事务并带回前一个片段。

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

fragmentTransaction.replace(containerViewId, fragment2);
fragmentTransaction.addToBackStack();
fragmentTransaction.commit();

和你的第 3 步:

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

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

这解释了为什么如果您返回活动,它是恢复的片段。但恐怕不是,为什么它显然与它的活动无关。

于 2013-05-22T20:33:30.967 回答