从文档开始:
public void setRetainInstance (boolean retain) 控制是否在 Activity 重新创建时(例如从配置更改)保留片段实例。这只能与不在后台堆栈中的片段一起使用。如果设置,片段生命周期将在重新创建活动时略有不同:不会调用 onDestroy() (但仍然会调用 onDetach(),因为片段正在与其当前活动分离)。 onCreate(Bundle) 不会被调用,因为片段没有被重新创建。 onAttach(Activity) 和 onActivityCreated(Bundle) 仍将被调用。
我有一些问题:
片段是否也保留其视图,或者会在配置更改时重新创建? “保留”究竟是什么意思?
当用户离开activity时,fragment会被销毁吗?
为什么它不适用于后堆栈上的片段?
在哪些用例中使用此方法有意义?
Fragment.onDestroy()
间歇性被调用,并且片段中的字段相应无效,据说受 setRetainInstance(true)
保护
首先,查看关于保留片段的my post。它可能会有所帮助。
现在回答你的问题:
片段是否还保留其视图状态,或者会在配置更改时重新创建 - 究竟什么是“保留”?
是的,Fragment
的状态将在配置更改期间保留。具体来说,“保留”意味着片段将在配置更改时被销毁。也就是说,即使配置更改导致底层 Activity
被破坏,Fragment
也会保留。
当用户离开activity时,fragment会被销毁吗?
就像Activity
一样,Fragment
可能会在内存资源不足时被系统销毁。您是否让片段在配置更改时保留其实例状态不会影响系统是否会在您离开 Activity
后销毁 Fragment
。如果您离开 Activity
(即按主页按钮),Fragment
可能会或可能不会被破坏。如果您通过按后退按钮离开 Activity
(因此,调用 finish()
并有效地销毁 Activity
),所有附加的 Activity
的 Fragment
也将被销毁。
为什么它不适用于后堆栈上的片段?
不支持它可能有多种原因,但对我来说最明显的原因是 Activity
持有对 FragmentManager
的引用,而 FragmentManager
管理后台堆栈。也就是说,无论您是否选择保留 Fragment
,Activity
(以及 FragmentManager
的后台堆栈)都会在配置更改时被销毁。它可能不起作用的另一个原因是,如果允许保留片段 和 非保留片段都存在于同一个 backstack 上,事情可能会变得棘手。
在哪些用例中使用此方法有意义?
保留的片段对于跨活动实例传播状态信息(尤其是线程管理)非常有用。例如,片段可以作为 Thread
或 AsyncTask
实例的宿主,管理其操作。有关详细信息,请参阅有关此主题的 my blog post。
一般来说,我会将它与将 onConfigurationChanged
与 Activity
一起使用...不要仅仅因为您太懒而无法正确实施/处理方向更改而将其用作创可贴。仅在需要时使用它。
setRetaininstance
仅在您的 activity
由于配置更改而被销毁并重新创建时有用,因为实例是在调用 onRetainNonConfigurationInstance
期间保存的。也就是说,如果您旋转设备,保留的片段将保留在那里(它们不会被破坏和重新创建。)但是当运行时终止活动以回收资源时,什么都不会留下。当您按下后退按钮并退出活动时,一切都被破坏了。
通常我使用这个功能来保存方向更改时间。假设我从服务器下载了一堆位图,每个是 1MB,当用户不小心旋转他的设备时,我当然不想再做所有的下载工作。所以我创建了一个 Fragment
来保存我的位图并将其添加到管理器并调用 setRetainInstance
,即使屏幕方向发生变化,所有位图仍然存在。
mActivity
引用。但我不知道在这种情况下运行时是否也会清除片段实例中的小部件。请尝试一下或深入研究源代码。
SetRetainInstance(true) 允许片段生存。其成员将在轮换等配置更改期间保留。但是当活动在后台被杀死时,它仍然可能被杀死。如果后台的包含活动被系统杀死,它的 instanceState 应该由您正确处理 onSaveInstanceState 的系统保存。换句话说,onSaveInstanceState 将始终被调用。虽然如果 SetRetainInstance 为 true 并且片段/活动尚未被杀死,则不会调用 onCreateView,但如果它被杀死并被尝试恢复,它仍然会被调用。
以下是对android活动/片段的一些分析,希望对您有所帮助。 http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html
setRetainInstance() - 已弃用
片段上的 setRetainInstance() 方法已被弃用。随着 ViewModel 的引入,开发人员可以使用特定的 API 来保留可以与活动、片段和导航图相关联的状态。这允许开发人员使用正常的、未保留的 Fragment 并将他们想要保留的特定状态分开,避免常见的泄漏源,同时保持保留状态的单个创建和销毁的有用属性(即 ViewModel 的构造函数以及它收到的 onCleared() 回调)。
setRetainInstance(boolean) 在您希望拥有一些不与 Activity 生命周期相关的组件时很有用。例如,rxloader 使用这种技术来“为 rxjava 的 Observable 处理 Android 的活动生命周期”(我发现 here)。
setRetainInstance(true)
,则Fragment
java 对象及其所有内容在旋转时不被破坏,但视图被重新创建.即再次调用onCreatedView()
。从 Android 1.0 开始,它基本上应该与Activities
一起使用。我不认为使用它是“懒惰的”,或者使用它是不“正确的”。事实上,我不明白为什么它不是默认设置,或者你为什么想要关闭它。Fragment
仅在配置更改时保留,其中基础活动将被销毁并立即重新创建。在活动被销毁的所有其他情况下,保留的片段也将被销毁。setRetainInstance(true)
,仍然必须实现自己的持久性(savedInstanceState
或其他)才能处理所有场景:例如“home键,旋转,返回应用程序”使用构造函数调用重新创建我的片段,丢失所有状态变量。我有一个AsyncTask
作为成员变量,这就是我想保留的原因,现在,如果我想让它工作,我不得不停止任务,保存状态,并在用户回来时恢复。所以总而言之,这只是帮助旋转的一种快速方法,但一般来说没有用。