使用 `onRetainCustomNonConfigurationInstance` 跨配置更改保留数据

Posted

技术标签:

【中文标题】使用 `onRetainCustomNonConfigurationInstance` 跨配置更改保留数据【英文标题】:Using `onRetainCustomNonConfigurationInstance` to retain data across configuration changes 【发布时间】:2015-08-20 19:19:56 【问题描述】:

我为 android 编程已经有一段时间了,我仍在寻找解决方案来保留配置更改时的数据。除了在onSaveInstanceState 文档中将Parcelables 保存到Activity 的Bundle 之外,还建议使用Fragment 并将setRetainInstance 标志设置为true。

但是我刚刚遇到了一些使用onRetainCustomNonConfigurationInstance 来保存任意对象的代码(以一种奇特的方式,但本质上是没有引用Activity 等的大对象)。没见过用过这种方法,所以有些疑惑:

调用此方法来存储任意对象是否安全(从某种意义上说,我可以很确定它会被调用,并且不会很快被弃用/删除)? 此方法与onRetainNonConfigurationInstance() 有何不同,onRetainNonConfigurationInstance() 也应该返回 Object,本质上应该类似地工作? 出于某种原因,使用保留片段是否更好?

作为奖励,我将不胜感激任何其他提示或解决方案来保存对象的状态,如 AsyncTaskObservable、视图的演示者并继续

【问题讨论】:

***.com/questions/15749106/… @JaredBurrows 感谢您的评论,但我认为这不仅不是最佳解决方案,而且在 Android 应用程序中处理状态丢失是错误且有害的方式。另外,它并不能真正解决问题(例如,在应用程序进入后台之后) @JaredBurrows:我同意 wasyl,因为您的解决方案并没有真正解决任何问题。充其量,您可以将您的方法用作将自身锁定到某些特定屏幕方向的活动的优化。否则,您仍然必须处理所有其余的配置更改(例如,语言环境、汽车坞站)并且您现在必须大惊小怪地处理 onConfigurationChanged() 方法中的每个单独的资源更改,以涵盖configChanges 阻止正常活动销毁/重新创建周期的情况。 “它不会很快被弃用/删除”——它在图书馆里。您可以控制何时采用较新版本的库。 “此方法与 onRetainNonConfigurationInstance() 有何不同” -- onRetainNonConfigurationInstance()final 并且不能被覆盖,以确保 FragmentActivity 可以对其片段进行配置更改工作。 onRetainCustomNonConfigurationInstance() 是在活动级别参与的替代“钩子”。 “出于某种原因,使用保留片段是否更好?” -- 它可以在FragmentActivity以外的地方工作。 “两者都应该以类似的方式工作,对吗?” -- 只要两者都应该在配置更改中保留,是的。 【参考方案1】:

调用此方法存储任意对象是否安全(在某种意义上 我可以很确定它会被调用,而且不会被调用 很快就会被弃用/删除)?

onRetainCustomNonConfigurationInstance() 是一种相对较新的方法,并未被弃用。我真的认为它不会很快消失,因为没有理由仅仅为了删除它而引入新的东西。您可以放心使用。

这个方法和onRetainNonConfigurationInstance()有什么不同, 哪个也应该返回 Object,本质上应该类似地工作?

onRetainNonConfigurationInstance() 总是返回内部NonConfigurationInstances 类的实例,其中保留了片段、加载器等状态。您不能(也不应该)更改此系统行为。这就是为什么方法是 final 并且您不能覆盖它的原因。

如果您想保留您的自定义实例,您需要覆盖 onRetainCustomNonConfigurationInstance() 并从那里返回它。

实际上,onRetainNonConfigurationInstance() 调用 onRetainCustomNonConfigurationInstance() 并保留重新调整的实例以及保留的片段和加载程序等其他状态。

出于某种原因,使用保留片段是否更好?

这取决于您的用例和偏好。逻辑可能是这样的。如果你的 Activity 只是控制 Fragment,没有其​​他特殊逻辑,那么使用 Retained Fragment 会更容易。如果您的活动有一些需要保留的内容,那么您可以安全地使用onRetainCustomNonConfigurationInstance() 方法。就目前而言,在这两种情况下,状态仍然通过旧的和已弃用的 onRetainNonConfigurationInstance() 方法保留。

附言关于存储状态的额外问题,我宁愿建议查看onSaveInstanceState() 方法。它用于存储状态。

更新:AndroidX release from November 5, 2018 弃用了该方法,并附上以下说明:onRetainCustomNonConfigurationInstance 已弃用。使用 ViewModel 来存储需要在配置更改后继续存在的对象。

【讨论】:

感谢您的回答!您能否评论 Activity source 第 1758 行的 javadoc 的 onRetainNonConfigurationInstance() 方法的一部分,其中说 此函数纯粹是作为优化调用的,您不能依赖它被调用。 ´onRetainNonConfigurationInstance()´ os 已弃用,这就是为什么您不应该依赖它并且您不需要,因为您应该使用保留的 Fragment 或 ´onRetainCustomNonConfigurationInstance()´ 一个没有这个警告。 当然,但是提供onRetainCustomNonConfigurationInstanceFragmentActivity 使用onRetainNonConfigurationInstance,在Activity 类(因此它的父级)中被标记为不可靠。所以在FragmentActivity 方法中onRetainCustom... 是从父级覆盖的onRetainNonConf... 调用的,而父级的文档说它不能保证被调用。抱歉,如果我不清楚,请告诉我是否需要改写我的意思;) 我会坚持将 API 作为 Android 框架和开发人员之间的官方合同。它通过它的弃用说“不要使用 onRetainNonConfigurationInstance”,它说“你可以使用 FragmentActivity.onRetainCustomNonConfigurationInstance()”,因为它是一个公共的,不被弃用的方法。一种方法调用另一种方法的事实不应该改变任何东西。一旦弃用的方法被删除或不被调用,它们仍然必须以某种方式为另一种方法提供支持(因为它是官方 API 的一部分)。他们有一定的可能违反规则,但恕我直言,这不是那么高。 截至 2018 年 11 月,onRetainNonConfigurationInstance 方法已弃用:developer.android.com/jetpack/androidx/androidx-rn#2018-nov

以上是关于使用 `onRetainCustomNonConfigurationInstance` 跨配置更改保留数据的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)