Android-如何保存界面状态

2,314 阅读3分钟

保存页面状态,可以在页面异常退出重建或者屏幕旋转等配置更改的情况下,回到之前的状态,使用户体验更好。

本文从保存对象的粒度区分: onSaveInstanceState() 和 ViewMadel

本地存储:是持久化存储方案。平时用的比较多,可以和上面两种配合使用。上面两种都是临时存储方案

onSaveInstanceState() 保存在磁盘,适合保存小对象。 ViewModel 保存在内存,适合保存复杂对象

onSaveInstanceState()

适用于由于内存紧张导致页面重建或者配置更改后页面重建,保存少量小对象数据

两种情况

  1. onSaveInstanceState()
  2. Fragment.setRetainInstance(true)的onSaveInstanceState
onSaveInstanceState()

是声明周期调用的。它保留了在以下两种情况下 UI 的相关数据:

  1. 由于内存限制,应用程序在后台运行时会停止。
  2. 配置更改

在 activity.onStop 之后 finish 之前调用。但是在用户调用finish或者主动关闭 activity 时,是不会调用的 (之前一直以为只有在异常状态才会调用,是错误的。而是在异常状态或者活动进入后台时都会被调用。) 在 android p 之后,在onStop 之后调用;P 之前,在onStop之前调用。 如果是主动关闭,那么是不会保存的

存储机制

保存在磁盘,activity关闭后,就会清除。 运行在主线程,适合保存小对象

Fragment.setRetainInstance(true)的onSaveInstanceState

是否在 Activity 重建时保留 fragment 实例。如果设置为 true,那么生命周期的调用不一样

  1. 不会调用 onDestroy(), 但是会调用 onDetach()
  2. onCreate() 不会调用,但 onAttach() 和 onActivityCreate() 会调用

图片地址

存储机制

保留在内存中.可以保存复杂对象

ViewModel

适用于在配置更改后重建页面时,恢复数据

负责为界面准备数据。在配置更改期间会自动保留 ViewModel 对象。这样页面重建后,不需要重新请求数据

  1. 不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。因为ViewModel 存在时间比activity 或者 fragment 声明周期长。

2.可以包含 LifeCycleObservers,如 LiveData .但是它不能观察对生命周期感知型可观察对象(LiveData.observe)

生命周期

正常情况,对于Activity.onDestroy() 时 结束。 Fragment.onDetach() 时结束。 对于异常状态,比如屏幕旋转导致的Activity 重建,并不会销毁 ViewModel。所以可以通过ViweModel恢复状态

存储机制

保存在内存。适合保存复杂对象

对比

ViewModel 是否可以替代onSaveInstanceState

分为两种情况:

一. onSaveInstanceState()

不能。但他们是配合使用

  1. ViewModel 只有在 Activity 因配置修改而重建时,才会保存实例。如果是异常状态退出,是不能保存实例的 而 onSaveInstanceState 可以在异常状态退出后,保存数据.
  2. 如果是配置修改导致的重建,ViewModel 实例没有重建,可以从内存中读取
  3. 如果异常状态导致重建, ViewModel 被销毁。只能从 onSaveInstanceState 中获取状态。但是 onSaveInstanceState 不能保存复杂对象。所以可以在 ViewModel 中将数据缓存到本地,onSaveInstanceState 保存数据 Id, 当重建后,根据 id 从本地存储中读取数据。

二. Fragment.setRetainInstance(true)的onSaveInstanceState

可以替代

  1. 这种情况下,Fragment 内部 view 已经销毁了,只是保留了数据。而 ViewModel 也可以保存数据
  2. ViewModel 内部也是通过调用 setRetainInstance(true) 来实现

ViewModel 和 onSaveInstanceState() 怎么配合使用

官方给出 SavedStateRegistry ,将 onSaveInstanceState() 和 ViewModel 关联。但实际还是 Bundle 来存取数据。

参考链接

保存界面状态

了解 Activity 生命周期

ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders

ViewModel 的已保存状态模块