【Jetpack Compose基础语法学与练】第8课 rememberSaveable,页面旋转/系统重建保留状态
前言上一课学习了 if 条件渲染和 LazyColumn 懒加载列表掌握动态UI与长列表渲染。我们一直用 remember 保存状态但它有一个致命缺陷手机旋转屏幕、系统因内存不足重建Activity时remember保存的数据会全部丢失重置为初始值。本课学习 rememberSaveable 它能在系统重建配置变更、进程重启时自动保存和恢复状态是真实安卓开发必须掌握的知识点。前置完成1~7课掌握remember、状态、基础布局与列表一、完整可运行示例源码packagecom.example.composefirstimportandroid.os.Bundleimportandroidx.activity.ComponentActivityimportandroidx.activity.compose.setContentimportandroidx.compose.foundation.layout.Columnimportandroidx.compose.foundation.layout.Spacerimportandroidx.compose.foundation.layout.heightimportandroidx.compose.foundation.layout.paddingimportandroidx.compose.material3.Buttonimportandroidx.compose.material3.Textimportandroidx.compose.runtime.Composableimportandroidx.compose.runtime.getValueimportandroidx.compose.runtime.mutableIntStateOfimportandroidx.compose.runtime.saveable.rememberSaveableimportandroidx.compose.runtime.setValueimportandroidx.compose.ui.Modifierimportandroidx.compose.ui.tooling.preview.Previewimportandroidx.compose.ui.unit.dpclassMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{SaveableDemoPage()}}}ComposablefunSaveableDemoPage(){// rememberSaveable系统重建时自动保存恢复varcountbyrememberSaveable{mutableIntStateOf(0)}Column(modifierModifier.padding(20.dp)){Text(text当前计数$count)Spacer(modifierModifier.height(12.dp))Button(onClick{count}){Text(1)}Spacer(modifierModifier.height(8.dp))Button(onClick{count0}){Text(重置)}}}PreviewComposablefunSaveablePreview(){SaveableDemoPage()}二、逐行代码解读rememberSaveable { mutableIntStateOf(0) }和 remember 用法几乎一模一样唯一区别数据会被序列化保存到Bundle中Activity因配置变更、系统重建的时候可以自动恢复数据。导入路径 androidx.compose.runtime.saveable.rememberSaveableremember 丢失数据的场景旋转屏幕、切换系统深色模式、修改系统字体大小、切换系统语言这些操作都会触发安卓配置变更销毁并且重建Activity。remember仅仅保存在运行时内存当中页面重建之后内存清空状态直接归零。rememberSaveable 底层原理封装安卓原生 onSaveInstanceState 保存机制把状态序列化放进Bundle页面重建之后从Bundle读取数据恢复状态。存在功能限制只能存储可以序列化的数据。整型、字符串、布尔值等基础类型开箱即用自定义实体类需要实现Parcelable或者手动提供Saver保存器。简单区分 rememberSaveable 和 ViewModelrememberSaveable 适合少量UI状态开箱即用代码简短。ViewModel 适合大批量业务数据、跨页面共享数据生命周期更长旋转屏幕不会丢失。ViewModel属于架构进阶内容后续课程再详细讲解。三、核心概念文字对比remember重组的时候可以保留状态屏幕旋转、页面重建数据丢失数据类型没有限制适合页面临时状态。rememberSaveable重组的时候可以保留状态屏幕旋转、页面重建自动恢复数据需要支持序列化适合表单、计数器等需要防丢失的数据。记忆口诀临时状态用remember怕丢数据用rememberSaveable。四、综合练习题填空题能够在旋转屏幕、系统重建时自动保存恢复状态的函数是________。rememberSaveable 底层基于安卓传统的________机制把数据存入Bundle。rememberSaveable 要求保存的数据类型必须是________的自定义类需要实现Parcelable。答案与解析rememberSaveable 解析专门用于跨配置变更、系统重建保存状态。onSaveInstanceState 解析安卓传统保存实例状态机制Compose封装后自动调用。可序列化解析Bundle只能存可序列化数据基础类型默认支持自定义类需Parcelable。判断题remember 和 rememberSaveable 在普通重组时都能保留数据效果一样。答案正确。理由两者在Compose重组时都会保存数据区别只在系统重建场景。用remember保存的计数器旋转屏幕后数值会重置为初始值。答案正确。理由remember只存在内存中Activity销毁重建后内存数据清空。rememberSaveable 可以保存任意类型的数据包括不可序列化的对象。答案错误。理由rememberSaveable基于Bundle存储数据必须可序列化不可序列化对象会运行时报错。简答题什么场景下应该使用rememberSaveable而不是remember举两个实际例子。参考答案当状态需要在系统重建旋转屏幕、语言切换、深色模式切换、内存回收重建后保留时使用。例子1用户在表单页输入了一半内容旋转屏幕后不能清空例子2计数器页面用户点了很多次旋转屏幕后数值要保留。代码实操题把第7课的待办列表示例改造输入文本和待办列表都使用rememberSaveable保存确保旋转屏幕后数据不丢失。写出关键状态定义代码。参考答案ComposablefunTodoListPage(){varinputTextbyrememberSaveable{mutableStateOf()}vartodoListbyrememberSaveable{mutableStateOf(listOfString())}funaddTodo(item:String){todoListtodoListitem}funremoveTodo(item:String){todoListtodoList-item}// ... 其余UI代码和第7课一致}解析inputText是字符串默认可序列化直接使用rememberSaveable。todoList采用不可变List增删时生成全新集合进行赋值正常触发重组。注意mutableStateListOf直接套rememberSaveable存在兼容隐患练习场景优先选用不可变列表。五、本课小结remember 仅重组保数据屏幕旋转、页面重建数据丢失。rememberSaveable 依托安卓实例保存机制系统重建自动恢复状态。存入的数据需要支持序列化自定义对象需要额外实现Parcelable。选型参考临时界面状态用remember需要防丢失的数据选用rememberSaveable。下一课SideEffect副作用 LaunchedEffect处理异步任务和生命周期。

相关新闻

深入解析 Pod_ContainerCreating 云盘挂载超时或冲突:基于 chaosblade 技能库的 K8s 故障演练实战指南

深入解析 Pod_ContainerCreating 云盘挂载超时或冲突:基于 chaosblade 技能库的 K8s 故障演练实战指南

运维云原生SREAI Agent人工智能 【免费下载链接】chaosblade An easy to use and powerful chaos engineering experiment toolkit.(阿里巴巴开源的一款简单易用、功能强大的混沌实验注入工具) 项目地址: https://gitcode.com/gh_mirrors/ch/…

2026/10/9 5:22:27 阅读更多 →
FlashInfer CuTeDSL MegaMoE 内核 drop 更新工作流:src 原样落地与 shim 适配层的维护实战

FlashInfer CuTeDSL MegaMoE 内核 drop 更新工作流:src 原样落地与 shim 适配层的维护实战

大模型深度学习算子库后端高性能计算 【免费下载链接】flashinfer FlashInfer: Kernel Library for LLM Serving 项目地址: https://gitcode.com/gh_mirrors/fl/flashinfer 点击查看 免费下载 本篇技术指南讲解 FlashInfer 的 moe_ep(MoE Expert Parall…

2026/10/9 5:22:27 阅读更多 →
三数之和双指针解法全解析:排序+去重,从暴力到O(n²)优化

三数之和双指针解法全解析:排序+去重,从暴力到O(n²)优化

1. 题目到底在考什么:先读懂三数之和1.1 题干回顾LeetCode 15 这道题,题面非常简洁:给你一个整数数组nums,要求找出所有三元组[nums[i], nums[j], nums[k]],满足三个下标互不相同,且三个数之和等于 0。输出…

2026/10/9 5:22:27 阅读更多 →

最新新闻

洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

洛谷P5732杨辉三角:二维数组递推、组合数陷阱与DP思维启蒙

1. 从一道入门题说起:为什么所有算法新手都绕不开杨辉三角洛谷P5732,题目全称是【深基5.习7】杨辉三角,属于洛谷"深入基础"系列第五章的练习题。这个系列是给刚学完语法、开始接触算法的人准备的,题目本身不难&#xff…

2026/10/9 5:53:55 阅读更多 →
网络排查不再靠感觉:掌握延迟丢包与DNS判断标准

网络排查不再靠感觉:掌握延迟丢包与DNS判断标准

干这行久了你会发现一个很残酷的事实:大家排查网络问题的时候,命令都会敲,工具都会用,但真正到了"判断结果"这一步,很多人是靠感觉的。ping一下网关通着,就觉得网络没事;tracert看到星…

2026/10/9 5:53:55 阅读更多 →
SpringBoot日志追踪实战:用MDC+拦截器实现全链路TraceId

SpringBoot日志追踪实战:用MDC+拦截器实现全链路TraceId

1. 从一次线上事故说起:为什么日志追踪非做不可今年年初我接手了一个“老带新”的SpringBoot电商项目,四个服务互相调用,平时开发联调问题不大,一上生产就乱了套。有一次商品库存扣减异常,用户反馈“明明支付成功但订单…

2026/10/9 5:53:55 阅读更多 →
MySQL、Redis、MQ、ES高可用方案选型与避坑实战

MySQL、Redis、MQ、ES高可用方案选型与避坑实战

1. 高可用不是“装个集群”就完事:四个组件的选型逻辑先理清很多人一提高可用,脑子里第一反应就是“上集群”。MySQL 搞个主从、Redis 弄个哨兵、MQ 搭个镜像队列、ES 配个副本分片,然后觉得万事大吉。我早期也这么干过,结果一次机…

2026/10/9 5:53:55 阅读更多 →
ASCII与Unicode编码详解:从原理到乱码排查实战

ASCII与Unicode编码详解:从原理到乱码排查实战

字符编码这东西,平时写代码时几乎感觉不到它的存在,可一旦出问题,那真是让人抓耳挠腮。乱码、问号、方块字、emoji显示成两个问号,这些场景我相信每个开发者都遇到过。我自己印象最深的一次,是帮朋友处理一个批量导入的…

2026/10/9 5:53:55 阅读更多 →
PS5折腾指南:Mesh Shader、DualSense驱动与双机端口转发解析

PS5折腾指南:Mesh Shader、DualSense驱动与双机端口转发解析

最近后台和社群里不少朋友都在搜 PS5 相关的折腾问题,从 GPU 架构、手柄驱动到路由器端口转发都有人问,而且问得越来越细。说实话,PS5 已经发售了这么多年,但真正把硬件规格、外设兼容、网络配置这几块讲透的内容反而不多——大部…

2026/10/9 5:52:54 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →