11-保存状态

2023-05-16

保存状态

文章目录

    • 保存状态
    • 用户预期和系统行为
      • 用户发起的界面状态解除
      • 系统发起的界面状态解除
    • 用于保留界面状态的选项
    • 使用 ViewModel 处理配置更改
    • 使用 onSaveInstanceState() 作为后备方法来处理系统发起的进程终止
    • 针对复杂或大型数据使用本地持久性存储来处理进程终止
    • 管理界面状态:分而治之
    • 恢复复杂的状态:重组碎片
    • 其他资源
      • 博客

未编辑

在发生系统发起的 Activity 或应用销毁后,需要及时保存和恢复 Activity 的界面状态,这是用户体验的一个至关重要的部分。在这些情况下,用户希望界面状态保持不变,但是系统会销毁 Activity 及其中存储的任何状态。

要使系统行为符合用户预期,可以把 ViewModel 对象、onSaveInstanceState() 方法和/或本地存储空间结合起来使用,从而在发生此类应用和 Activity 实例转换后保持界面状态。在决定如何组合这些选项时,需要考虑界面数据的复杂程度、应用的用例以及检索速度与内存用量的权衡。

无论采用哪种方法,都应确保应用满足用户对其界面状态的预期,并提供流畅、简洁的界面(消除将数据载入界面过程中的延迟时间,尤其是在发生像旋转这样频繁的配置更改之后)。在大多数情况下,您应同时使用 ViewModel 和 onSaveInstanceState()。

本页讨论了用户对界面状态的预期,可用于保留状态的选项,以及每种选项的权衡因素和局限性。

用户预期和系统行为

根据用户执行的操作,他们会希望系统清除或保留 Activity 状态。在某些情况下,系统会自动执行用户预期的操作。但有时,系统会执行与用户预期相反的操作。

用户发起的界面状态解除

用户希望当他们启动 Activity 时,该 Activity 的暂时性界面状态会保持不变,直到用户完全关闭 Activity 为止。用户可以通过以下方式完全关闭 Activity:

  • 按返回按钮
  • 从“概览”(“最近使用的应用”)屏幕中滑动关闭 Activity
  • 从 Activity 向上导航
  • 从“设置”屏幕中终止应用
  • 完成某种“完成”Activity(由 Activity.finish() 提供支持)

在这些完全关闭的情况下,用户会认为他们已经永久离开 Activity,如果他们重新打开 Activity,会希望 Activity 以干净的状态启动。系统在这些关闭场景中的基础行为符合用户预期,即 Activity 实例将连同其中存储的任何状态以及与该 Activity 关联的任何已保存实例状态记录一起被销毁并从内存中移除。

关于完全关闭的此规则有一些例外情况,例如用户可能希望浏览器为他们打开的是他们在使用返回按钮退出浏览器之前查看的网页。

系统发起的界面状态解除

用户希望 Activity 的界面状态在发生配置更改(例如旋转或切换到多窗口模式)后保持不变。但是,默认情况下,系统会在发生此类配置更改时销毁 Activity,从而清除存储在 Activity 实例中的任何界面状态。要详细了解设备配置,请参阅配置参考页面。请注意,您可以替换针对配置更改的默认行为,但不建议这样做。如需了解详情,请参阅自行处理配置更改。

如果用户暂时切换到其他应用,稍后再返回到您的应用,他们也会希望 Activity 的界面状态保持不变。例如,用户在您的搜索 Activity 中执行搜索,然后按主屏幕按钮或接听电话,当他们返回搜索 Activity 时,希望看到搜索关键字和结果仍在原处,并和之前完全一样。

在这种情况下,您的应用会被置于后台,系统会尽最大努力将您的应用进程留在内存中。但是,当用户转而去与其他应用进行互动时,系统可能会销毁该应用进程。在这种情况下,Activity 实例连同其中存储的任何状态都会一起被销毁。当用户重新启动应用时,Activity 会出乎意料地处于干净状态。要详细了解进程终止行为,请参阅进程和应用生命周期。

用于保留界面状态的选项

当用户对界面状态的预期与默认系统行为不符时,您必须保存并恢复用户的界面状态,以确保系统发起的销毁对用户完全透明。

按照以下几个会影响用户体验的维度考量,用于保留界面状态的每个选项都有所差异:

ViewModel已保存实例状态持久性存储空间
存储位置在内存中已序列化到磁盘在磁盘或网络上
在配置更改后继续存在
在系统发起的进程终止后继续存在
在用户完成 Activity 关闭/onFinish() 后继续存在
数据限制支持复杂对象,但是空间受可用内存的限制仅适用于基元类型和简单的小对象,例如字符串仅受限于磁盘空间或从网络资源检索的成本/时间
读取/写入时间快(仅限内存访问)慢(需要序列化/反序列化和磁盘访问)慢(需要磁盘访问或网络事务)

使用 ViewModel 处理配置更改

ViewModel 非常适合在用户正活跃地使用应用时存储和管理界面相关数据。它支持快速访问界面数据,并且有助于避免在发生旋转、窗口大小调整和其他常见的配置更改后从网络或磁盘中重新获取数据。要了解如何实现 ViewModel,请参阅 ViewModel 指南。

ViewModel 将数据保留在内存中,这意味着成本要低于从磁盘或网络检索数据。ViewModel 与一个 Activity(或其他生命周期所有者)相关联,在配置更改期间保留在内存中,系统会自动将 ViewModel 与发生配置更改后产生的新 Activity 实例相关联。

当用户退出您的 Activity 或 Fragment 时,或者在您调用 finish() 的情况下,系统会自动销毁 ViewModel,这意味着状态会被清除,正如用户在这些场景中所预期的一样。

与已保存实例状态不同,ViewModel 在系统发起的进程终止过程中会被销毁。因此,您应将 ViewModel 对象与 onSaveInstanceState()(或其他一些磁盘持久性功能)结合使用,并将标识符存储在 savedInstanceState 中,以帮助视图模型在系统终止后重新加载数据。

如果您已有用于在发生配置更改后存储界面状态的内存中解决方案,则可能不需要使用 ViewModel。

使用 onSaveInstanceState() 作为后备方法来处理系统发起的进程终止

onSaveInstanceState() 回调会存储一些数据,如果系统销毁后又重新创建界面控制器(如 Activity 或 Fragment),则需要使用这些数据重新加载该控制器的状态。要了解如何实现已保存实例状态,请参阅 Activity 生命周期指南中的“保存和恢复 Activity 状态”。

已保存实例状态捆绑包在配置更改和进程终止后都会保留,但受限于存储容量和速度,因为 onSavedInstanceState() 会将数据序列化到磁盘。如果序列化的对象很复杂,序列化会占用大量的内存。因为此过程在配置更改期间发生在主线程上,所以如果耗时太长,序列化可能会导致丢帧和视觉卡顿。

请勿将 onSavedInstanceState() 用于存储大量的数据(如位图),也不要用于存储需要冗长的序列化或反序列化操作的复杂数据结构,而是只能用于存储基本类型和简单的小对象,例如字符串。因此,请使用 onSaveInstanceState() 存储最少量的数据(例如 ID),如果其他持久性机制失效,需要使用这些数据来重新创建必要的数据以将界面恢复到之前的状态。大多数应用都应实现 onSaveInstanceState() 来处理系统发起的进程终止。

根据应用的用例,您可能完全不需要使用 onSaveInstanceState()。例如,浏览器可能会将用户带回他们在退出浏览器之前正在查看的确切网页。如果 Activity 表现出这种行为,则您可以放弃使用 onSaveInstanceState(),改为在本地保留所有内容。

此外,如果您从 intent 打开 Activity,则当配置发生更改以及系统恢复该 Activity 时,会将 extra 捆绑包传送给该 Activity。在 Activity 启动时,如果一段界面状态数据(例如搜索查询)作为 intent extra 传入,则您可以使用 extra 捆绑包而不是 onSaveInstanceState() 捆绑包。要详细了解 intent extra,请参阅 Intent 过滤器和 Intent 过滤器。

在上述任一情况下,您仍然可以使用 ViewModel 来避免因在配置更改期间从数据库重新加载数据而浪费周期时间。

如果要保留的是简单的轻量级界面数据,那么您可以单独使用 onSaveInstanceState() 来保留状态数据。

注意:您现在可以通过 ViewModel 的已保存状态模块(目前为 Alpha 版)在 ViewModel 对象中提供对已保存状态的访问途径。已保存状态可通过 SavedStateHandle 对象来访问。您可以在 Android 生命周期感知型组件 Codelab 中查看其使用方式。

针对复杂或大型数据使用本地持久性存储来处理进程终止

只要您的应用安装在用户的设备上,持续性本地存储(例如数据库或共享偏好设置)就会继续存在(除非用户清除应用的数据)。虽然此类本地存储空间会在系统启动的活动和应用进程终止后继续存在,但由于必须从本地存储空间读取到内存,因此检索成本高昂。这种持久性本地存储通常已经属于应用架构的一部分,用于存储您打开和关闭 Activity 时不想丢失的所有数据。

ViewModel 和已保存实例状态均不是长期存储解决方案,因此不能替代本地存储空间,例如数据库。您只应该使用这些机制来暂时存储瞬时界面状态,对于其他应用数据,应使用持久性存储空间。请参阅应用架构指南,详细了解如何充分利用本地存储空间长期保留您的应用模型数据(例如在重启设备后)。

管理界面状态:分而治之

您可以通过在各种类型的持久性机制之间划分工作,高效地保存和恢复界面状态。在大多数情况下,这些机制中的每一种都应存储 Activity 中使用的不同类型的数据,具体取决于数据复杂度、访问速度和生命周期的权衡:

  • 本地持久性存储:存储在您打开和关闭 Activity 时不希望丢失的所有数据。

    • 示例:歌曲对象的集合,其中可能包括音频文件和元数据。
  • ViewModel

    :在内存中存储显示关联界面控制器所需的所有数据。

    • 示例:最近搜索的歌曲对象和最近的搜索查询。
  • onSaveInstanceState()
    

    :存储当系统停止后又重新创建界面控制器时轻松重新加载 Activity 状态所需的少量数据。这里指的是将复杂的对象保留在本地存储空间中,并将这些对象的唯一 ID 存储在

    onSaveInstanceState()
    

    中,而不是存储复杂的对象。

    • 示例:存储最近的搜索查询。

例如,假设有一个用于搜索歌曲库的 Activity。应按如下方式处理不同的事件:

当用户添加歌曲时,ViewModel 会立即委托在本地保留此数据。如果新添加的这首歌曲应显示在界面中,则您还应更新 ViewModel 对象中的数据以表明该歌曲已添加。切记在主线程以外执行所有数据库插入操作。

当用户搜索歌曲时,针对界面控制器从数据库加载的任何复杂歌曲数据都应立即存储在 ViewModel 对象中。您还应将搜索查询本身保存在 ViewModel 对象中。

当 Activity 进入后台时,系统会调用 onSaveInstanceState()。您应将搜索查询保存在 onSaveInstanceState() 捆绑包中。该少量数据很容易保存。这也是使 Activity 恢复到当前状态所需的所有信息。

恢复复杂的状态:重组碎片

当到了用户该返回 Activity 的时候,重新创建 Activity 存在两种可能情况:

  • 在系统停止 Activity 后重新创建该 Activity。该 Activity 将查询保存在 onSaveInstanceState() 捆绑包中,并且应将查询传递给 ViewModelViewModel 发现它没有缓存搜索结果,并使用指定的搜索查询委托加载搜索结果。
  • 在配置更改后创建 Activity。该 Activity 将查询保存在 onSaveInstanceState() 捆绑包中,而且 ViewModel 已缓存搜索结果。您将查询从 onSaveInstanceState() 捆绑包传递到 ViewModel,以此确定它已加载必要的数据,且无需要从数据库重新查询数据。

注意:最初创建 Activity 时,onSaveInstanceState() 捆绑包不包含任何数据,且 ViewModel 对象为空。创建 ViewModel 对象时,您将传递空白查询,以此告知 ViewModel 对象尚没有要加载的数据。因此,Activity 以空状态启动。

其他资源

要详细了解如何保存界面状态,请参阅以下资源。

博客

  • ViewModel:简单示例
  • ViewModel:持久性、onSaveInstanceState()、恢复界面状态和加载器
  • Android 生命周期感知型组件 Codelab
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

11-保存状态 的相关文章

  • 8021x认证以及portal认证的参考资料

    最近几个月一直在阅读和认证相关的东西 xff0c 到如今 xff0c 也基本上将认证的流程摸得比较清楚了 xff0c 所以在这里写一篇文章 xff0c 记录一下自己的心得 同时也给希望了解这些认证的同学一些参考资料 说实话 xff0c 在没
  • 枚举类返回前端处理

    后端经常使用的枚举类 xff0c 在返回给前段 xff0c 会之间显示枚举名称 xff0c 不是很友好 xff0c 可以通过以下方法解决 枚举类上加 64 JsonFormat 注解 例如以下代码 maven lt dependency g
  • BW:BW与第三方BI接口设计与实现:APD、Open Hub、RFM

    最近公司新上了国内某 CRM系统 xff0c SAP的 CRM也光荣下线了 但是紧接着就出现了一些需求 xff0c CRM自带一款小型 BI xff0c 需要一些 SD的数据 xff0c 但是把 R3的数据给他们进行计算的话 xff0c 不
  • Spring源码解读(一)启动流程分析——AbstractApplicationContext

    前言 通过对Spring启动流程源码的分析 xff0c 能够使我们对spring掌握的更透彻 本篇博文通过5 2 19版本的源码以 new ClassPathXmlApplicationContext 34 classpath spring
  • Spring源码解读(十四)Boot启动类——SpringApplication.run

    前言 继 Spring源码解读 xff08 十三 xff09 Boot启动类 SpringApplication构造方法 后 xff0c 继续分析SpringApplication run方法 程序入口 启动方法中增加一些boot的新特性处
  • 拓扑排序(Topological Sorting)

    一 什么是拓扑排序 在图论中 xff0c 拓扑排序 xff08 Topological Sorting xff09 是一个有向无环图 xff08 DAG Directed Acyclic Graph xff09 的所有顶点的线性序列 且该序
  • Gnome3提取gnome-shell.css以及修改和编译

    原帖 xff1a http hack fdzh org item id 61 522 GNOME 3 12 开始使用 GResource 二进制资源文件保存 js css svg 等文件 xff0c 需使用 gresource 解压 xff
  • docker网络故障排查(重启firewall导致docker启动失败)

    背景 xff1a 生产环境需要用docker发布新的应用 xff0c 结果docker启动失败 xff0c 报了iptables异常 先说导致这个问题的原因 xff1a firewall是基于iptables工具来管理防火墙 xff0c d
  • java内嵌tomcat并启动

    java内嵌tomcat并启动 创建工程 创建maven工程ee tomat embed pom xml添加依赖如下 lt properties gt lt project build sourceEncoding gt UTF 8 lt
  • 20210525:Python学习——re.compile()查找数据是遇到换行

    re compile r 39 lt div class 61 34 sub 34 gt lt div gt 39 re S 被采集的数据中有多行 xff0c 有换行符所以要加re S或者re DOTALL xff0c 换行读取数据 xff
  • 再见,2012,你好,2013.

    其实这篇日志过年前 xff0c 已经写得差不多 xff0c 但是忘记发了 xff0c 现在补上 xff0c 现在应该还不是太晚吧 ps xff1a 想了一个很俗的标题 61 61 2012年 xff0c 是对我意义最不平凡的一年 这一年 x
  • SpringSecurity之CSRF漏洞保护

    1 csrf简介 CSRF Cross Site Request Forgery跨站请求伪造 xff0c 也可称为一键式攻击 one click attack 通常缩写为CSRF或者XSRF CSRF攻击是一种挟持用户在当前已登录的浏览器上
  • GIS开发学习推荐书目

    书名 作者 出版社 版次 GIS 基础 地理信息系统导论 US Kang tsung Chang xff1b 陈健飞 译 电子工业出版社 第七版 ArcGIS地理信息系统空间分析实验教程 汤国安 杨昕 科学出版社 第二版 编程 基础 C语言
  • CSDN 还是不能改头像!!!

    都好几个月了 xff0c 技术问题么 xff0c 还是爬梯开大会 xff0c 连这个都不让改了 真不爽
  • 自己写的HTML与浏览器用截图工具量出来的尺寸不一致

    自己写的HTML与浏览器用截图工具量出来的尺寸不一致border style dashed height 200px width 200px border width 2px border color chartreuse 明显大了50px
  • 网站链接被微信屏蔽禁止访问的解决办法

    最近网站链接被微信屏蔽禁止访问 xff0c 微信内打开网址显示如下提醒 xff1a 已停止访问该网页 xff0c 网页包含诱导分享 关注等诱导行为内容 xff0c 被多人投诉 xff0c 为维护绿色上网环境 xff0c 已停止访问 出现这种
  • 由于找不到vcruntime140_1.dll,无法继续执行代码

    welcome to my blog 问题描述 安装mysql时报错 由于找不到vcruntime140 1 dll 无法继续执行代码 解决方法 这是缺少了动态链接库 ddl文件 跟mysql无关 下载这个ddl文件即可 打开下载地址 找到
  • Ubuntu 18.04 nvidia驱动导致的循环登陆解决

    Ubuntu 18 04 nvidia驱动导致的循环登陆解决 一般情况 无法进入登陆界面 xff1a 建议连接外接显示器看看效果 xff0c 或许有意外的惊喜驱动未安装 显卡未成功切换 自带驱动为屏蔽等 xff1a 请自行尝试百度其它解决方
  • linux下adb连接不上解决方法

    linux下adb连接不上解决方法 参考文章 xff1a xff08 1 xff09 linux下adb连接不上解决方法 xff08 2 xff09 https www cnblogs com asin huang p 8604368 ht

随机推荐

  • 这么学,好玩,有趣,逗死了!(2017年系统规划与管理师上午综合知识试题试题解析(六))

    IT服务风险管理中 xff0c 对风险的识别是很重要的一项工作 识别方法中 xff0c 通常采用文档审查 信息收集技术 检查表 分析假设和图解技术 下面 xff08 xff09 选项不属于信息采集技术 xff08 51 xff09 A 德尔
  • 松滋历史(1)--松滋县建县历史考证

    刘鲋鮈总共4个儿子 xff1a 刘建德 刘梁 刘延年 刘度 长沙顷王刘鲋鮈的儿子刘梁 汉昭帝始元六年 xff08 公元前81年 xff09 xff0c 六月乙未封高城节侯 汉宣帝元康元年 xff08 公元前65年 xff09 xff0c 正
  • 松滋历史(2)--高成县为什么这么高光?

    东汉开国皇帝刘秀 xff0c 是长沙定王刘发第5代世孙 也就是说 xff0c 东汉开国皇帝刘秀爷爷的爷爷与高城侯刘梁 xff08 高城县 xff08 松滋县前身 xff09 创始人 xff09 的爷爷是亲兄弟 在哪个特别讲血统的年代 xff
  • 为什么要报考系统架构设计师考试

    为什么要报考系统架构师考试 最近一年多 xff0c 很多朋友来信 xff0c 问我什么要报考系统架构设计师考试 为什么参加这个考试 xff0c 这个考试有用吗 xff1f 对自己的职业会带来什么好处 xff1f 我想有以下几个方面 xff1
  • 2014年24段魔尺变三叶花视频教程

    2014年24段魔尺变三叶花视频教程 xff08 升级版 xff09 偶是真心喜欢24段魔尺制作的三叶花 xff0c 那是相当漂亮 xff0c 体现了几何美 xff0c 对称美 xff0c 空间美 xff0c 色彩美 xff0c 见下图 三
  • BW:LO数据源初始化步骤(精简版)

    首先在r3上删除 setup table xff0c 然后再填充 setup table xff08 锁定凭证 xff09 xff0c 同时 xff0c 在bw做无数据的初始化 xff0c 最后在bw做full load
  • 24段魔尺,可以折出哪些精美图案

    24段魔尺 xff0c 可以折出哪些精美图案 24段魔尺 xff0c 究竟可以叠成哪些精美图案 xff1f 球 小乌龟 十字架 三叶花 三角形 牛魔王 音符是大家比较熟悉的 偶对这个问题 xff0c 比较感兴趣 先将网络上流传的24段魔尺折
  • 软考证到底有多大个鸟用?

    软考证到底有多大个鸟用 xff1f 小虎以信息系统项目管理师高级证书为例 xff0c 来说说这个证 xff0c 到底有什么用 xff1f 1 求职简历上 xff0c 可以浓彩重抹一笔 xff0c 好好吹嘘下自己 xff0c 是IT高级人才
  • 明朝开国第一重臣李善长长子李祺之长子李芳后裔在松滋

    明朝开国第一重臣李善长长子李祺之长子李芳后裔在松滋 李善长 xff0c 何许人也 肩比汉代丞相萧何 xff1b 功臣里排位第一 xff0c 比刘伯温 徐达 汤和 常遇春 蓝玉 李文忠地位高 xff1b 太师 xff0c 左丞相 xff0c
  • 程序员很少上《非诚勿扰》电视节目相亲之分析

    程序员很少上 非诚勿扰 电视节目相亲之分析 偶观看有线电视32 频道的江苏卫视 非诚勿扰 电视相亲节目 xff0c 半年有余 问题 为什么程序员很少上 非诚勿扰 节目进行相亲呢 xff1f 难道是程序员当中 xff0c 很少有大龄的剩男剩女
  • 2018年CSDN博客排名第一名,花落谁家?

    截止2018年10月9日 https blog csdn net stpeace 小虎问题 xff1a 通过搜索引擎例如 xff1a 百度 搜狗 Bing等 如何快速搜索 xff0c 定位谁是CSDN博客的第几名 xff1f 想知道谁CSD
  • 客家刘开七、刘广传刘氏七律族诗赏析V2.0

    七律 刘氏族诗 南宋 刘广传 骏马骑行各出疆 xff0c 任从随地立纲常 年深外境皆吾境 xff0c 日久他乡即故乡 早晚勿忘亲命语 xff0c 晨昏须顾祖炉香 苍天佑我卯金氏 xff0c 八七男儿共炽昌 一 平仄性赏析 除了 卯 字 xf
  • 系统mysql、sqlserver数据库兼容方案

    一 技术选型 springboot2 4 43 mybatisplus3 4 43 mysql5 7 43 redis3 0 43 二 编写目的 如果产品开发默认数据库采用mysql xff0c 但是当客户提出数据库需要采用Sqlserve
  • eclipse maven plugin 插件 安装 和 配置

    离线插件 点击下载离线安装包 xff1a eclipse maven plugin zip for eclipse helios or higher 解压缩到任意目录 xff08 如这里的plugins目录 xff09 xff1a 目录路径
  • Android 使用View Binding来代替频繁findViewById来得到view

    从 Android Studio 3 6 开始 xff0c 视图绑定能够通过生成绑定对象来替代 findViewById xff0c 从而可以帮您简化代码 移除 bug xff0c 并且从 findViewById 的模版代码中解脱出来 在
  • 李开复辞职前后的故事

    这些故事出自即将发售的 世界因你不同 xff1a 李开复自传 一书 xff0c 由李开复本人和北京青年报记者范海涛合写而成 以下为故事部分节选 xff1a 今天 xff0c 我开得很慢 xff0c 仿佛是让自己的心情在辽阔的天空下能够更加安
  • 哈哈,终于知道CSDN怎么改头像了

    话说之前一直郁闷 xff0c 说改头像的功能还没修好 xff0c 一直说服务器错误 今天偶尔发现 xff0c 右上角有个设置 xff0c 原来在这里可以改 我还发了几封邮件给CSDN的admin xff0c 居然只知道道歉 xff0c 不告
  • tail -f 在串口中查看日志文件

    tail f opt log log mi tail follow opt log log mi 如果想从串口中查看日志文件 用tail 命令就可以了
  • 10-WorkManager

    WorkManager 文章目录 WorkManager概览使用入门将WorkManager添加到项目中创建后台任务配置运行任务的方式和时间将任务提交给系统后续步骤 方法指南定义WorkRequest工作约束初始延迟重试和退避政策定义任务的
  • 11-保存状态

    保存状态 文章目录 保存状态用户预期和系统行为用户发起的界面状态解除系统发起的界面状态解除 用于保留界面状态的选项使用 ViewModel 处理配置更改使用 onSaveInstanceState 作为后备方法来处理系统发起的进程终止针对复