Activity & Fragment 的重建、数据恢复相关问题

2020-09-19  本文已影响0人  你可记得叫安可

0. onSaveInstanceState & onRestoreInstanceState 的时机

我们经常在网上看到说,onSaveInstanceStateActivity 退回到后台,且未来可能被系统杀死时,我们可以在 onSaveInstanceState 中保存一些临时数据,以便在系统真的杀死了进程,并回收了 Activity 后,用户回到 Activity 时,开发者能够在重建的 ActivityonCreateonRestoreInstanceState 方法中,能够从 Bundle 中恢复数据。

1. onCreate 和 onRestoreInstanceState 两个回调中都带有恢复数据用的 Bundle 参数,为什么两个地方都可以恢复?

这两个回调的时机不一样。

2. 那些情况下会被重建?

我们知道在屏幕旋转时 ActivityFragment 会重建,其实还有一种情况会重建,就是我们时常看到博客里说的,当应用在后台时,进程被系统回收,用户再次回到应用时,应用会被重建。

那么应用什么时候会被系统回收呢?我们需要清楚一点,就是系统不会单独地回收 Activity 或者 Fragment,而是会在系统资源不足时,根据应用所在的进程的状态来杀死进程,以回收资源。这里涉及到了一些进程状态的概念:前台进程、可见进程、服务进程 和 缓存进程(process lifecycle)。一般缓存进程会最先被系统回收。

现在的手机 RAM 都非常大,我们怎么模拟这个系统回收进程的过程呢?可以到 开发者选项 -> 应用 -> 后台进程限制,将其从默认的 标准限制 改为 不得超过 1 个进程。这样我们就能够观察到 ActivityFragment 重建时,Bundle 中带有之前调用 onSaveInstanceState 时保存的值了。

3. Fragment 重建时的回调为什么没有 onRestoreInstanceState

Fragement 的数据恢复提供了另外两个回调,onCreateonCreateView,方便开发者在不同的时机恢复数据。

4. Fragment.setRetainInstance 是如何保持 Fragment 的?

FragmentretainInstance 属性默认为 false,当其设置为 true 时,表示 Fragment 实例会在 Activity 因配置变化而重建时,Fragment 自身实例会被保持,不会创建新的实例。它的原理是,调用该方法时,最终调用到了 FragmentManager.addRetainedFragment -> FragmentManagerViewModel.addRetainedFragmentFragment 实例保存到了 FragmentManagerViewModel.mRetainedFragments 中。mRetainedFragment 是一个以 Fragmentuuid(Fragment 自己生成)key,以 Fragment 自身实例为 valueHashMap。因此本质上是 FragmentManagerViewModel 是一个 ViewModel,它可以在重建周期内保持实例。

retainInstance 设置为 true 之后,Fragment 的生命周期会有所变化。由于会保存实例,因此重建时不会再调用 onDestroy 销毁,也不会再调用 onCreate 重新实例化。但是 onDetachonAttach 依然会调。

5. 什么时候用 onSaveInstanceState,什么时候用 ViewModel,什么时候用 Fragment.setRetainInstance?

正确的使用姿势应该是,onSaveInstanceStateViewModel 结合使用。

5. 怎么样可以使 Activity & Fragment 不再重建?

6. onRetainCustomNonConfigurationInstance & onRetainNonConfigurationInstance 的作用

我们知道 onSaveInstanceState 中保存的是能够被序列化的数据,Android 系统同样为我们提供了在配置改变时保存没有必要序列化的数据的方法:onRetainCustomNonConfigurationInstanceonRetainNonConfigurationInstance,这两个回调方法都返回一个 Object,区别在于,onRetainCustomNonConfigurationInstance 是开放给开发者来保存数据的时机的回调,onRetainNonConfigurationInstancefinal 方法,用于系统自己保存一些系统资源时使用。
对于 onRetainCustomNonConfigurationInstance 保存的数据,之后我们在重建的 ActivityonCreate 方法中,可以通过 getLastCustomNonConfigurationInstance 来直接获得之前保存的数据。这个回调在 Androidx 中已经被标记为 Deprecated,这是因为该机制的职责已经由 ViewModel 代替了。
对于 onRetainNonConfigurationInstance 保存的数据,其实通过阅读源码我们是可以发现,目前的实现就是用来保存了 ViewModel。而 ViewModel 之所以能够在系统配置改变后重建,正是使用了 onRetainNonConfigurationInstance 的恢复机制。

7. ViewModel 如何解决重建问题的?

上一篇下一篇

猜你喜欢

热点阅读