setRetainInstance上的文档说:



所以我开始玩。

我有一个 Activity ,并添加了第一个片段A

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

然后从这个碎片中运行父 Activity 的方法,该方法将碎片B添加到后堆栈
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new OrderFragment());
ft.addToBackStack(null);
ft.commit();

然后我从onCreate,onDestroy,onSaveInstanceState,onActivityCreated等创建日志消息

我尝试此过程的两个版本。在每个片段上旋转设备。
  • 默认

  • 一切都如预期。 onCreate,onDestroy在片段上射击
  • setRetainInstance(true)

  • 一切都如预期吗?片段上的onCreate,onDestroy不会触发

    并且所有片段似乎都可以在片段位于后端堆栈中时工作。.那么,为什么文档说我不应该使用它呢?
    在哪些情况下我可能会遇到麻烦?

    谢谢

    最佳答案

    更新的答案:



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

    (我不确定开发人员是否会实际尝试此操作,因为使用setRetainInstance(true)使onSaveInstanceState()有点多余,但是我没有看到API文档中记录的行为,所以我写下了这个答案)。

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

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

    调用addToBackStack()而不是setRetainInstance(true);

  • onCreate()onDestroy()被调用。
  • onSaveInstanceState()传递的 bundle 包作为onCreateView()中的参数被接收。

  • 同时调用addToBackStack()setRetainInstance(true):
  • onCreate()onDestroy()不被调用。 API文档中提到了这一点。
  • onSaveInstanceState()中未收到从onCreateView()传递的分发包。传入的Bundle为null。

  • 使用记录的方法调用和参数测试为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()
  • 带有 bundle 软件参数的
  • onCreateView()!=空
  • onStart()
  • onResume()

  • 测试2和3:使用setRetainInstance(true)调用,addToBackStack()调用/未调用的片段生命周期调用(结果相同):
  • onAttach()
  • onCreateView()
  • onActivityCreated()
  • onStart()
  • onResume()

  • [设备从纵向旋转为横向]
  • onPause()
  • onSaveInstanceState()
  • onStop()
  • onDestroyView()
  • onDetach()
  • onAttach()
  • 带有 bundle 软件参数== null的
  • onCreateView()
  • onStart()
  • onResume()
  • 10-04 10:20