24

setRetainInstance 上的文档说:

这只能与不在后台堆栈中的片段一起使用。

所以我开始玩它。

我有一个添加第一个片段 A 的 Activity

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...等创建日志消息

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

  1. 默认

一切都如预期的那样。onCreate, onDestroy on Fragments 触发

  1. 设置保留实例(真)

一切如预期?onCreate, onDestroy on Fragments 不触发

当片段在后台时,一切似乎都可以工作..那么为什么文档说我不应该使用它?在哪些情况下我可能会遇到麻烦?

谢谢

4

1 回答 1

26

更新的答案:

在哪些情况下我可能会遇到麻烦?

将 a 添加Fragment到后台堆栈并在配置更改时将 aBundleFragmentfrom传递onSaveInstanceState()到。onCreateView()调用setRetainInstance(true)将在配置更改时将 设置Bundle为空。

(我不确定开发人员是否真的会尝试这样setRetainInstance(true)做,因为 usingonSaveInstanceState()有点多余,但我没有看到 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为空。

记录方法调用和参数的测试是否为空:

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()
  • 开始()
  • onResume()

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

  • 暂停()
  • onSaveInstanceState()
  • 停止()
  • onDestroyView()
  • onDestroy()
  • onDetach()
  • onAttach()
  • onCreate()
  • 带有捆绑参数的 onCreateView() != null
  • 开始()
  • onResume()

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

  • onAttach()
  • onCreateView()
  • onActivityCreated()
  • 开始()
  • onResume()

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

  • 暂停()
  • onSaveInstanceState()
  • 停止()
  • onDestroyView()
  • onDetach()
  • onAttach()
  • onCreateView() 与捆绑参数 == null
  • 开始()
  • onResume()
于 2012-12-08T01:23:24.947 回答