理解Fragment的setRetainInstance(boolean)

Ixx*_*Ixx 328 android android-fragments

从文档开始:

public void setRetainInstance(boolean retain)

控制是否在活动重新创建(例如从配置更改)中保留片段实例.这只能用于不在后栈中的片段.如果设置,则在重新创建活动时,片段生命周期会略有不同:

  • onDestroy()不会被调用(但是onDetach()仍然会被调用,因为片段正在与其当前活动分离.
  • 因为片段没有被重新创建,所以不会调用onCreate(Bundle).
  • onAttach(Activity)和onActivityCreated(Bundle)仍将被调用.

我有一些问题:

  • 片段是否也保留其视图,还是会在配置更改时重新创建?"保留"究竟是什么意思?

  • 当用户离开活动时,片段是否会被销毁?

  • 为什么它不适用于后端堆栈上的碎片?

  • 哪个是使用此方法有意义的用例?

Ale*_*ood 332

首先,查看关于保留碎片的帖子.它可能有所帮助.

现在回答你的问题:

片段是否也保留其视图状态,或者是否会在配置更改时重新创建 - 究竟是什么"保留"?

是的,Fragment状态将在整个配置更改中保留.具体而言,"保留"意味着在配置更改时不会破坏该片段.也就是说,即使配置更改导致底层被破坏,Fragment也将保留Activity.

当用户离开活动时,片段是否会被销毁?

就像Activitys 一样,Fragment当内存资源不足时,系统可能会破坏s.无论您的片段是否在配置更改中保留其实例状态,都不会影响系统是否会在Fragment您离开后破坏s Activity.如果你离开Activity(即通过按下主页按钮),Fragments可能会或可能不会被销毁.如果你Activity按下后退按钮(因此,调用finish()并有效地摧毁它Activity),所有Activity附加的Fragments也将被销毁.

为什么它不适用于后端堆栈上的碎片?

可能有多种原因导致它不被支持,但对我来说最明显的原因是它Activity拥有对thestack 的引用FragmentManager,并且FragmentManager管理backstack.也就是说,无论你是否选择保留你的Fragments,都会在配置改变时销毁Activity(因而FragmentManager背板).它可能不起作用的另一个原因是因为如果允许保留的片段非保留的片段都存在于同一个后台上,事情可能会变得棘手.

哪个是使用此方法有意义的用例?

保留的片段对于跨活动实例传播状态信息(尤其是线程管理)非常有用.例如,一个片段可以作为实例的主机ThreadAsyncTask,管理其操作.有关详细信息,请参阅关于此主题的博客文章.

一般情况下,我会把它当作onConfigurationChangedActivity...一样使用它不要仅仅因为你太懒而无法正确实现/处理方向更改.只在需要时使用.

  • 据我所知,如果你有`setRetainInstance(true)`,那么`Fragment` java对象及其所有内容在旋转时都不会被破坏,但视图*被重新创建.那就是再次调用`onCreatedView()`.它基本上是自Android 1.0以来应该与`Activities`一起使用的方式.我不认为使用它是"懒惰",或使用它不是"适当的".事实上,我不明白为什么它不是默认值,或者为什么你会想要它. (97认同)
  • 不保留视图对象,它们在配置更改时始终被销毁. (33认同)
  • 我找到了你的解释"为什么它不适用于后堆栈上的碎片?" 很难理解.但也许我很笨:( (24认同)
  • @dierre可以通过多种方式销毁活动.例如,如果单击"返回",则活动将被销毁.如果单击"home",活动将停止,并且在内存不足时可能会在将来的某个时间销毁.保留的`Fragment`s仅保留在配置更改中,其中要销毁并立即重新创建的基础活动.在活动被销毁的所有其他情况下,保留的碎片也将被销毁. (12认同)
  • @AlexLockwood你可以确认以下内容:即使使用`setRetainInstance(true)`,仍然*必须*实现自己的持久性(`savedInstanceState`或其他)以便能够处理所有场景:例如"home key,旋转,回到应用程序"使用构造函数调用重新创建我的片段,丢失所有状态变量.我有一个`AsyncTask`作为成员变量,这就是我想保留的原因,现在,如果我想让它工作,我被迫停止任务,保存状态,并在用户回来时恢复.总而言之,这只是一种帮助轮换的快速方法,但总的来说无用. (3认同)
  • 令我烦恼的是,我必须去 Google 员工的博客才能理解“onRetainInstance”,而不是官方 Android 文档! (2认同)
  • 您仍然需要覆盖`onSaveInstanceState()`来保存应用程序的状态.`setRetainInstance(true)`只保留配置更改中的片段......但是,由于其他原因,活动/片段仍然可能被破坏(即用户按下主页按钮,之后由于内存不足而导致进程被终止等) . (2认同)

sui*_*shi 27

setRetaininstance仅在activity因配置更改而销毁和重新创建因为实例在调用期间保存时才有用onRetainNonConfigurationInstance.也就是说,如果您旋转设备,保留的片段将保留在那里(它们不会被销毁并重新创建.)但是当运行时杀死活动以回收资源时,不会留下任何内容.当您按下后退按钮并退出活动时,一切都将被销毁.

通常我使用这个功能来保存方向更改Time.Say我从服务器下载了一堆Bitmaps,每个都是1MB,当用户不小心旋转他的设备时,我当然不想再做所有的下载工作了.所以我创建一个Fragment握住我的位图并将其添加到管理器并调用setRetainInstance,即使屏幕方向改变,所有位图仍然存在.


小智 12

SetRetainInstance(true)允许片段生存.其成员将在配置更改期间保留,如轮换.但是当活动在后台被杀死时它仍然可能被杀死.如果后台中的包含活动被系统杀死,那么它的instanceState应该由您在onSaveInstanceState上正确处理的系统保存.换句话说,将始终调用onSaveInstanceState.虽然如果SetRetainInstance为true且片段/活动尚未被杀死,则不会调用onCreateView,但如果它被杀死并被试图被带回,它仍然会被调用.

以下是对android活动/片段的一些分析希望它有所帮助. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html

  • 我肯定看到在旋转屏幕时再次在保留的片段上调用onCreateView. (7认同)

Gas*_*lén 8

setRetainInstance() - 已弃用

作为片段版本 1.3.0-alpha01

Fragments 上的 setRetainInstance() 方法已被弃用。随着 ViewModel 的引入,开发人员拥有一个特定的 API 来保留可以与活动、片段和导航图相关联的状态。这允许开发人员使用一个正常的、不保留的 Fragment 并将他们想要保留的特定状态分开,避免常见的泄漏源,同时保持单个创建和销毁保留状态(即 ViewModel 的构造函数)的有用属性以及它接收的 onCleared() 回调)。