保存页面状态,可以在页面异常退出重建或者屏幕旋转等配置更改的情况下,回到之前的状态,使用户体验更好。
本文从保存对象的粒度区分: onSaveInstanceState() 和 ViewMadel
本地存储:是持久化存储方案。平时用的比较多,可以和上面两种配合使用。上面两种都是临时存储方案
onSaveInstanceState() 保存在磁盘,适合保存小对象。 ViewModel 保存在内存,适合保存复杂对象
onSaveInstanceState()
适用于由于内存紧张导致页面重建或者配置更改后页面重建,保存少量小对象数据
两种情况
- onSaveInstanceState()
- Fragment.setRetainInstance(true)的onSaveInstanceState
onSaveInstanceState()
是声明周期调用的。它保留了在以下两种情况下 UI 的相关数据:
- 由于内存限制,应用程序在后台运行时会停止。
- 配置更改
在 activity.onStop 之后 finish 之前调用。但是在用户调用finish或者主动关闭 activity 时,是不会调用的 (之前一直以为只有在异常状态才会调用,是错误的。而是在异常状态或者活动进入后台时都会被调用。) 在 android p 之后,在onStop 之后调用;P 之前,在onStop之前调用。 如果是主动关闭,那么是不会保存的
存储机制
保存在磁盘,activity关闭后,就会清除。 运行在主线程,适合保存小对象。
Fragment.setRetainInstance(true)的onSaveInstanceState
是否在 Activity 重建时保留 fragment 实例。如果设置为 true,那么生命周期的调用不一样
- 不会调用 onDestroy(), 但是会调用 onDetach()
- onCreate() 不会调用,但 onAttach() 和 onActivityCreate() 会调用
存储机制
保留在内存中.可以保存复杂对象
ViewModel
适用于在配置更改后重建页面时,恢复数据
负责为界面准备数据。在配置更改期间会自动保留 ViewModel 对象。这样页面重建后,不需要重新请求数据
- 不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。因为ViewModel 存在时间比activity 或者 fragment 声明周期长。
2.可以包含 LifeCycleObservers,如 LiveData .但是它不能观察对生命周期感知型可观察对象(LiveData.observe)
生命周期
正常情况,对于Activity.onDestroy() 时 结束。 Fragment.onDetach() 时结束。 对于异常状态,比如屏幕旋转导致的Activity 重建,并不会销毁 ViewModel。所以可以通过ViweModel恢复状态
存储机制
保存在内存。适合保存复杂对象。
对比
ViewModel 是否可以替代onSaveInstanceState
分为两种情况:
一. onSaveInstanceState()
不能。但他们是配合使用
- ViewModel 只有在 Activity 因配置修改而重建时,才会保存实例。如果是异常状态退出,是不能保存实例的 而 onSaveInstanceState 可以在异常状态退出后,保存数据.
- 如果是配置修改导致的重建,ViewModel 实例没有重建,可以从内存中读取
- 如果异常状态导致重建, ViewModel 被销毁。只能从 onSaveInstanceState 中获取状态。但是 onSaveInstanceState 不能保存复杂对象。所以可以在 ViewModel 中将数据缓存到本地,onSaveInstanceState 保存数据 Id, 当重建后,根据 id 从本地存储中读取数据。
二. Fragment.setRetainInstance(true)的onSaveInstanceState
可以替代
- 这种情况下,Fragment 内部 view 已经销毁了,只是保留了数据。而 ViewModel 也可以保存数据
- ViewModel 内部也是通过调用 setRetainInstance(true) 来实现
ViewModel 和 onSaveInstanceState() 怎么配合使用
官方给出 SavedStateRegistry ,将 onSaveInstanceState() 和 ViewModel 关联。但实际还是 Bundle 来存取数据。
参考链接
ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders