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

(remember / retain / rememberSaveable / rememberSerializable)

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


一、为什么需要这些 API?

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

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

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


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

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

三、remember

1️⃣ 定义

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

val state = remember { mutableStateOf(0) }

2️⃣ 生命周期

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

Composable 离开 Composition,状态就消失


3️⃣ 典型使用场景

✅ UI 临时状态
✅ 动画状态
✅ 只和当前 Composable 有关的状态

@Composable
fun ExpandableCard() {
    var expanded by remember { mutableStateOf(false) }
    ...
}

4️⃣ 不要用在这里

❌ 用户输入
❌ Tab 选中状态
❌ 滚动位置
❌ 需要跨旋转保存的状态


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

1️⃣ 定义

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

val player = retain {
    ExoPlayer.Builder(appContext).build()
}

2️⃣ 生命周期

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

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


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

“保持同一个实例(===)”

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

4️⃣ 适合的对象类型

✅ 不能序列化的大对象
✅ 播放器(ExoPlayer)
✅ 缓存、控制器、引擎
✅ Flow / Channel / 协程相关对象


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

不能引用 Activity / Fragment / View / Lifecycle

// ❌ 错误
retain { MyManager(activity) }
// ✅ 正确
retain { MyManager(applicationContext) }

五、rememberSaveable

1️⃣ 定义

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

var count by rememberSaveable { mutableStateOf(0) }

2️⃣ 生命周期

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

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

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

4️⃣ 自定义对象(Saver)

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 变体

@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

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐