首页 文章

我怎么能用setRetainInstance(true)破坏碎片并将它们添加到backstack?

提问于
浏览
23

setRetainInstance上的文档说:

这只能用于不在后栈中的片段 .

所以我开始玩它 .

我有一个Activity添加第一个frag A

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new PackageFragment());
ft.commit

然后从这个frag我运行一个父Activity的方法,它将frag B添加到backstack

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new OrderFragment());
ft.addToBackStack(null);
ft.commit();

然后我从onCreate,onDestroy,onSaveInstanceState,onActivityCreated ......等创建log msg

我尝试了这个过程的两个版本 . 在每个片段上旋转设备 .

  • 默认

一切都如预期 . onCreate,onDestroy on fragment fire

  • setRetainInstance(true)

一切都如预期的那样? onCreate,onDestroy片段不要开火

当片段都在后台时,一切似乎都有效..所以为什么文档说我不应该使用它?我可能遇到麻烦的情况是什么?

谢谢

1 回答

  • 24

    更新的答案:

    我可能遇到麻烦的情况是什么?

    Fragment 添加到后端堆栈并在配置更改时将 Fragment 中的 BundleonSaveInstanceState() 传递到 onCreateView() . 调用 setRetainInstance(true) 会在配置更改时将 Bundle 设置为null .

    (我不确定开发人员是否真的会尝试这个,因为使用 setRetainInstance(true) 会使 onSaveInstanceState() 变得多余,但我没有看到API文档中记录的行为所以我写了这个答案) .

    如果同时调用了 addToBackStack()setRetainInstance(true) ,则与仅调用 addToBackStack() 相比, setRetainInstance() 会部分更改配置更改时的 Fragment 生命周期方法调用和参数值 .

    具体来说,在下面的测试中,查看仅调用 addToBackStack() 和调用 setRetainInstance(true) 之间的差异,并查看配置更改时发生的情况:

    拨打 addToBackStack() 但不是 setRetainInstance(true) ;

    • onCreate()onDestroy() 被调用 .

    • onSaveInstanceState() 传递的包作为 onCreateView() 中的参数被接收 .

    同时调用 addToBackStack()setRetainInstance(true)

    • onCreate()onDestroy() 未被调用 . 这在API文档中提到 .

    • onCreateView() 未收到 onSaveInstanceState() 传递的捆绑包 . 传入的 Bundle 为空 .

    对已记录的方法调用和参数测试为null的测试:

    Activity

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        MyFragment fragment;
        if (savedInstanceState != null) {
            fragment = (MyFragment) getFragmentManager().findFragmentByTag("my_fragment_tag");
        } else {
            fragment = new MyFragment();
            FragmentTransaction t = getFragmentManager().beginTransaction();
            t.addToBackStack(null);//toggle this
            t.add(android.R.id.content, fragment, "my_fragment_tag").commit(); 
        }
    }
    

    Fragment

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);//toggle this
    }
    

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("test", "value");
        super.onSaveInstanceState(outState);
    }
    

    测试1:调用 addToBackStack() 时的片段生命周期,并且不调用 setRetainInstance(true)

    • onAttach()

    • onCreate()

    • onCreateView()

    • onActivityCreated()

    • onStart()

    • onResume()

    [设备从纵向旋转到横向]

    • onPause()

    • onSaveInstanceState()

    • onStop()

    • onDestroyView()

    • onDestroy()

    • onDetach()

    • onAttach()

    • onCreate()

    • onCreateView() with bundle param != null

    • onStart()

    • onResume()

    测试2和3:调用 setRetainInstance(true) 的片段生命周期调用, addToBackStack() 调用/未调用(相同结果):

    • onAttach()

    • onCreateView()

    • onActivityCreated()

    • onStart()

    • onResume()

    [设备从纵向旋转到横向]

    • onPause()

    • onSaveInstanceState()

    • onStop()

    • onDestroyView()

    • onDetach()

    • onAttach()

    • onCreateView() with bundle param == null

    • onStart()

    • onResume()

相关问题