2013-02-25 42 views
24

我指的是Why use Fragment#setRetainInstance(boolean)?是用碎片的setRetainInstance(真)真的是一个很好的做法来处理旋转变化

我之所以问那么是Activity来处理旋转,Official Activity Documentation鼓励我们,让Activity关机和轮换期间重新启动

android:configChanges列出活动 将自行处理的配置更改。当运行时发生配置更改时, 活动默认关闭并重新启动,但使用此属性声明 配置将会阻止重新启动活动 。相反,该活动仍在运行,并调用其onConfigurationChanged()方法。注意:应该避免使用此属性 ,并仅将其用作最后的手段。请阅读处理 运行时间更改以了解有关如何正确处理由于配置更改而导致的重新启动 的更多信息。

任何尝试更改此Activity默认行为似乎都是不好的做法。为避免重新启动时重新加载耗时的数据结构,我们使用onRetainNonConfigurationInstancegetLastNonConfigurationInstance。 - Official Handling Runtime Changes

但是,当涉及处理片段中的旋转时,Google会给我们不同的建议吗?他们不希望我们关闭并重新启动Fragment?

public Object onRetainNonConfigurationInstance()

此方法已被废弃在代替API级别13.使用新片段API setRetainInstance(布尔值);通过Android兼容性软件包,旧款 平台也可以使用此功能。

  1. 为什么谷歌鼓励我们关停和旋转过程中重新启动活动,但鼓励我们旋转过程中保持片段?
  2. 如果setRetainInstance(true)擅长处理轮换,Google为什么不将它作为Fragment的默认行为?

回答

29
  • 配置更改:当突然屏幕变得更广泛,高度(典型横向)少得多,这是易于为可视组件以更新其显示和更智能地使用可用的屏幕。配置更改的另一个示例是用户滑动硬件键盘,更改设备语言等。为什么要重新启动:

    • Android组件支持声明性布局,您加载了一堆XML布局,并从那里开始工作。查找每个视图并实时重新安排/更新它将是一团糟,更不用说所有事件处理程序和其他自定义View代码的重新布线。它更容易重新加载另一堆布局文件。另外,在Android中,活动的种类活在系统的摆布之中,所以自然而然,活动生命周期是如此设计(并推荐)的,它能随时按需重新创建自己,就像它在它被摧毁之前。这种模式适用于所有的重新启动,这也归因于配置更改。如果你让你的活动和片段能够维持一个永恒的状态,那么配置的改变就不是什么大问题。

    • 保留状态数据(模型),而不是显示它的东西(UI和视图)。

  • setRetainInstance(真):建议只对与不持有任何东西任何参考片段,将要在旋转重新使用。这意味着你不应该在任何持有上下文,视图等的片段上使用它。典型的Visual片段可以。但对于持有像运行线程,AsyncTasks,数据集合,加载资产,获取结果等对象的碎片,这是非常有用的。这种方法有助于使用非可视碎片作为可拆卸的持有者,用于活动的非依赖于上下文的对象。

+0

是的忘记了为什么它不聪明的使用视图,但上下文泄漏是答案。 – Warpzit 2013-02-25 12:03:11

+1

**“只能与不包含任何将在循环中重新创建的引用的片段一起使用。”**我不太确定这是否100%准确。如果保留的片段在'onActivityCreated(Bundle)'中设置了对父Activity的引用(这将在每次配置更改后在保留的片段中调用),那么这应该不足以确保保留的'Fragment'从来没有提到一个旧的“活动”? – 2013-04-22 00:10:12

+3

@AlexLockwood如果你看源代码,'FragmentManager'设置一个片段的'mActivity'字段为其在attach时的父活动,并且当该片段被分离时,也将其设置回null **。在可由'getActivity()'访问的片段中。因此,并不总是需要存储对父活动的另一个引用,并且如果这样做,则必须在分离时清除/释放它。诚然,如果你足够小心以确保你不会泄漏上下文引用,你可以以任何方式使用它。我的目的是阻止在任何Fragment上无意识地使用'setReatainInstance()'。 – 2013-04-22 04:52:00

4

因为你误解了它的用法。 setRetainInstance(true)只能用于像独奏元素/模块的片段。处理套接字等的片段没有真正受益于被保留的GUI。带有GUI的碎片应该不会使用setRetainInstance(true)。此外,任何进入后台的碎片都不应该使用setRetainIstance(true)

你可以把它推广到任何只处理数据/连接等的片段应该使用setRetainInstance(true)。但是有很多不同的方法来使用片段,这不会从setRetainInstance(true)中受益。

+1

支持你的想法的任何来源? Google Android文档没有特别针对UI和非UI片段。 – 2013-02-25 11:58:24

+0

如果你看看setRetainInstance上的google引用(true),它至少不会与backstack一起使用。链接:http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean) – Warpzit 2013-02-25 12:01:12