🧸 rememberSaveable

📱 屏幕旋转 · 进程重建

⚡ 状态持久化核心 —— rememberSaveable 在 Activity 重建与进程终止时自动保存/恢复,是 Compose 状态管理的“安全网”。

📌 1. 为什么需要 rememberSaveable?

🔄 屏幕旋转

Configuration 改变导致 Activity 重建,Compose 树被销毁。普通 remember 丢失状态。

💀 进程重建

App 在后台被系统杀死,用户返回时重新创建进程。rememberSaveable 通过 Bundle 恢复。

🧪 2. 基本使用

语法与 remember 类似,但值会被序列化到 SavedStateHandle。

// 基础用法:自动保存/恢复
var count by rememberSaveable { mutableStateOf(0) }

// 自定义 Saver (例如保存非 Bundle 支持的类型)
var user by rememberSaveable(saver = UserSaver()) {
    mutableStateOf(User("小智", 12))
}

📊 对比 · remember / rememberSaveable

特性rememberrememberSaveable
🎯 生命周期Composition 存活期间Composition + Activity 重建 / 进程恢复
📦 序列化不需要需要 (Bundle / Saver)
⚡ 屏幕旋转❌ 丢失✅ 自动恢复
🧩 自定义类型直接存储需实现 Saver 或 Parcelable/Serializable

⚠️ 3. 使用限制 & 注意事项

🧭 4. 保存与恢复流程 (SVG 架构)

🔄 重建触发 📦 SavedStateHandle Bundle 序列化 💾 保存到 Bundle 📂 从 Bundle 恢复 ♻️ 重组 Composable 🧩 rememberSaveable 自动桥接

🔧 5. 自定义 Saver (处理复杂对象)

当类型不是 Bundle 原生支持时,实现 Saver 或使用 mapSaver / listSaver。

// 示例:保存一个数据类 User
data class User(val name: String, val age: Int)

val UserSaver = Saver<User, String>(
    save = { user -> "${user.name}:${user.age}" },
    restore = { str ->
        val parts = str.split(":")
        User(parts[0], parts[1].toInt())
    }
)

// 使用
var user by rememberSaveable(saver = UserSaver) {
    mutableStateOf(User("小明", 10))
}

📌 典型场景 & 推荐方案

场景推荐方案说明
表单输入 (文本/开关)rememberSaveable屏幕旋转后保留用户输入
列表选中状态rememberSaveable + Saver保存选中 index 或 id 列表
网络请求结果ViewModel + StateFlow避免 Bundle 过大,且进程重建时重新加载
动画进度/播放状态rememberSaveable简单浮点/布尔值直接保存
大对象 / BitmapViewModel + 磁盘/DataStoreBundle 不适合,进程重建需持久化

⏳ 6. 生命周期对比 (remember vs rememberSaveable)

remember 存活期 ✖ rememberSaveable 存活期 ⚡ 屏幕旋转 → 丢失 ✅ 旋转/进程重建 → 恢复

🎯 核心要点