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

And*_*cko 24 android android-fragments android-orientation

setRetainInstance上的文档说:

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

所以我开始玩它.

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

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new PackageFragment());
ft.commit
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  1. 默认

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

  1. setRetainInstance(真)

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

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

谢谢

Gun*_*son 26

更新的答案:

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

当添加Fragment到背堆以及使BundleFragmentonSaveInstanceState()onCreateView()上配置改变.调用setRetainInstance(true)Bundle在配置更改时设置为null.

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

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

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

打电话addToBackStack()但不打电话setRetainInstance(true);

  • onCreate()并被onDestroy()称为.
  • 从中传递的包onSaveInstanceState()作为参数接收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(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

Fragment:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setRetainInstance(true);//toggle this
}
Run Code Online (Sandbox Code Playgroud)

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putString("test", "value");
    super.onSaveInstanceState(outState);
}
Run Code Online (Sandbox Code Playgroud)

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