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

时间:2013-04-08 11:39:36

标签: android android-fragments onresume back-stack

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

Application flow

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

    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()

    问题

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

3 个答案:

答案 0 :(得分:2)

如果Activity未显示用户界面,然后显示用户界面,则FragmentManager关联的所有片段都会消失,您需要恢复其状态。

正如documentation所说:

  

在很多情况下,片段可能会被大部分拆除(例如放置在没有显示UI的后台堆栈上),但是在其拥有的活动实际需要保存其状态之前,其状态将不会被保存。

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

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

试一试,祝你好运! : - )

答案 1 :(得分:1)

我不知道会发生这种情况,除非(基于你如何描述这些步骤)你误解了fragmentTransaction.addToBackStack()是如何工作的:它管理哪些事务放在backstack中,而不是片段。

来自android docs:

  

通过调用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放在顶部。

这解释了为什么返回活动时它是恢复的片段。但不,我担心,为什么它显然脱离了它的活动。

答案 2 :(得分:1)

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

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