compose中 remember retain rememberSaveable、rememberSerializable的区别

Jetpack Compose 状态生命周期说明文档

(remember / retain / rememberSaveable / rememberSerializable)

本文基于 Google 官方 Compose 文档
State lifespans in Compose


一、为什么需要这些 API?

Compose 中的状态,默认是短命的

kotlin 复制代码
val x = 0
  • 每次重组都会重新执行
  • Activity 重建后一定丢失
  • 进程被杀后完全消失

为了解决 "状态应该活多久" 的问题,Compose 提供了不同层级的状态保存机制。


二、状态生命周期总览(先看结论)

API 跨重组 跨配置变化(旋转等) 进程被杀后恢复 核心特点
remember 只对抗重组
retain 保持同一个实例
rememberSaveable 基于 SavedState
rememberSerializable 基于 kotlinx.serialization

三、remember

1️⃣ 定义

在当前 Composition 中缓存一个值,避免重组时重新创建

kotlin 复制代码
val state = remember { mutableStateOf(0) }

2️⃣ 生命周期

  • ✅ 重组(Recomposition)
  • ❌ Activity 重建
  • ❌ 进程被杀

Composable 离开 Composition,状态就消失


3️⃣ 典型使用场景

✅ UI 临时状态

✅ 动画状态

✅ 只和当前 Composable 有关的状态

kotlin 复制代码
@Composable
fun ExpandableCard() {
    var expanded by remember { mutableStateOf(false) }
    ...
}

4️⃣ 不要用在这里

❌ 用户输入

❌ Tab 选中状态

❌ 滚动位置

❌ 需要跨旋转保存的状态


四、retain(官方 API,容易被忽略)

1️⃣ 定义

在配置变化时保留同一个对象实例(不做序列化)

kotlin 复制代码
val player = retain {
    ExoPlayer.Builder(appContext).build()
}

2️⃣ 生命周期

  • ✅ 重组
  • ✅ Activity 重建(旋转等)
  • ❌ 进程被杀

⚠️ 不会保存到 Bundle,不会 restore


3️⃣ retain 的核心语义(非常重要)

"保持同一个实例(===)"

  • 不重新创建
  • 不做序列化
  • 类似 onRetainNonConfigurationInstance

4️⃣ 适合的对象类型

✅ 不能序列化的大对象

✅ 播放器(ExoPlayer)

✅ 缓存、控制器、引擎

✅ Flow / Channel / 协程相关对象


5️⃣ retain 的铁律(必须遵守)

不能引用 Activity / Fragment / View / Lifecycle

kotlin 复制代码
// ❌ 错误
retain { MyManager(activity) }
kotlin 复制代码
// ✅ 正确
retain { MyManager(applicationContext) }

五、rememberSaveable

1️⃣ 定义

在 remember 的基础上,把状态保存到 SavedStateRegistry

kotlin 复制代码
var count by rememberSaveable { mutableStateOf(0) }

2️⃣ 生命周期

  • ✅ 重组
  • ✅ 配置变化
  • ✅ 进程被杀后恢复

3️⃣ 默认支持的数据类型

  • Int / Long / Boolean
  • String
  • Parcelable
  • Serializable

4️⃣ 自定义对象(Saver)

kotlin 复制代码
data class UiState(val a: Int, val b: Int)

val state = rememberSaveable(
    saver = listSaver(
        save = { listOf(it.a, it.b) },
        restore = { UiState(it[0], it[1]) }
    )
) {
    UiState(0, 0)
}

5️⃣ 典型使用场景

✅ 用户输入

✅ Tab / 页面选中状态

✅ 滚动位置

✅ 表单数据


六、rememberSerializable(官方 API)

1️⃣ 定义

专门为 kotlinx.serialization 提供的 rememberSaveable 变体

kotlin 复制代码
@Serializable
data class UserUiState(
    val name: String,
    val age: Int
)

val state = rememberSerializable {
    UserUiState("", 0)
}

2️⃣ 生命周期

  • ✅ 重组
  • ✅ 配置变化
  • ✅ 进程被杀后恢复

3️⃣ 和 rememberSaveable 的区别

对比点 rememberSaveable rememberSerializable
保存机制 Bundle + Saver kotlinx.serialization
是否写 Saver 可能需要 不需要
适合对象 Android 风格 纯 Kotlin 数据

4️⃣ 适合的项目类型

✅ MVI / Redux

✅ 纯数据 UI State

✅ 跨平台 / KMP 项目


七、官方推荐使用顺序(经验法则)

UI 状态选择优先级

复制代码
ViewModel(业务状态)
↓
rememberSaveable / rememberSerializable(用户状态)
↓
retain(不可序列化的长期对象)
↓
remember(临时 UI 状态)

八、你作为 Android 工程师应该怎么用?

常见场景对照表

场景 正确选择
动画展开 / 收起 remember
Tab 选中 rememberSaveable
输入框内容 rememberSaveable
播放器 / 引擎 retain
UI State(data class) rememberSerializable
网络数据 ViewModel

九、一句话总结(定锚点)

  • remember:对抗重组
  • retain:保持实例,跨配置
  • rememberSaveable:SavedState
  • rememberSerializable:序列化 UI State

相关推荐
stevenzqzq6 天前
compose Effect概念
compose
stevenzqzq7 天前
Compose 核心组件学习指南
compose
stevenzqzq8 天前
compose中的@Stable概念和用法
compose
码农搬砖_20209 天前
【一站式学会compose】 Android UI体系之 Image的使用和介绍
android·image·compose·content·contentscale·scaletype
stevenzqzq9 天前
Compose重组的概念1
命令模式·compose
stevenzqzq9 天前
compose中 DisposableEffect和onDispose
compose
stevenzqzq10 天前
compose中 SideEffect概念以及作用
compose
码农搬砖_202010 天前
【一站式学会compose】 Android UI体系之 Text的使用和介绍
android·compose
stevenzqzq10 天前
Compose基础入门
开发语言·compose