在 Jetpack Compose 中,State(状态)是 UI 响应式更新的核心。Compose 提供了多种 State 管理方式,主要包括以下几种:
1️⃣ remember:临时状态
- 适用场景:存储 UI 生命周期内的可变状态,不会在重组中丢失,但不会跨配置变更(如屏幕旋转)。
- 使用方式:
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value++ }) {
Text("Count: ${count.value}")
}
- 等价于:
var count by remember { mutableStateOf(0) }
2️⃣ rememberSaveable:跨配置变更的状态
- 适用场景:与
remember类似,但它能在配置更改(如屏幕旋转)后保持状态。 - 使用方式:
var text by rememberSaveable { mutableStateOf("") }
TextField(value = text, onValueChange = { text = it })
- 底层机制:使用
SavedInstanceState进行存储。
3️⃣ mutableStateOf:单一值状态
- 适用场景:用于简单的数据存储,会触发 UI 重组。
- 使用方式:
val isChecked = remember { mutableStateOf(false) }
Checkbox(checked = isChecked.value, onCheckedChange = { isChecked.value = it })
4️⃣ derivedStateOf:避免不必要的重组
- 适用场景:当
State依赖于另一个State计算时,避免在每次 recomposition 重新计算。 - 使用方式:
val list = remember { mutableStateOf(listOf(1, 2, 3, 4, 5)) }
val evenNumbers by remember { derivedStateOf { list.value.filter { it % 2 == 0 } } }
- 作用:
evenNumbers只有在list变化时才会重新计算,而不会在 UI 重组时重新计算。
5️⃣ produceState:将 Flow/异步数据转换为 State
- 适用场景:将
Flow、suspend function结果转换成State,适用于网络请求、数据库查询等异步数据。 - 使用方式:
val timeState = produceState(initialValue = 0) {
while (true) {
delay(1000)
value++
}
}
Text("Seconds: ${timeState.value}")
6️⃣ snapshotFlow:监听 State 变化并转为 Flow
- 适用场景:将 Compose
State转换为Flow进行监听,适用于与协程结合的数据流操作。 - 使用方式:
val count = remember { mutableStateOf(0) }
LaunchedEffect(Unit) {
snapshotFlow { count.value }
.collect { println("Count changed to $it") }
}
7️⃣ collectAsState:从 Flow 获取 State
- 适用场景:从
Flow获取 UI 状态并更新 Compose 界面,适用于 ViewModel 处理数据流。 - 使用方式:
val viewModel: MyViewModel = viewModel()
val uiState by viewModel.uiStateFlow.collectAsState()
- 底层机制:会自动取消订阅
Flow并在Composed组件销毁时停止收集。
8️⃣ LaunchedEffect:副作用处理
- 适用场景:执行只需运行一次的副作用,比如网络请求、数据库读取。
- 使用方式:
LaunchedEffect(Unit) {
delay(2000)
println("This runs once when the composition enters")
}
9️⃣ rememberCoroutineScope:管理 CoroutineScope
- 适用场景:在 Composable 中启动协程,不会因为重组而重新创建协程作用域。
- 使用方式:
val coroutineScope = rememberCoroutineScope()
Button(onClick = {
coroutineScope.launch {
delay(1000)
println("Coroutine executed")
}
}) {
Text("Start Task")
}
🔟 rememberUpdatedState:获取最新的 State
- 适用场景:在
LaunchedEffect或SideEffect内,避免State过时的问题。 - 使用方式:
val latestValue = rememberUpdatedState(newValue)
LaunchedEffect(Unit) {
delay(3000)
println("Latest value: ${latestValue.value}") // 确保始终获取最新值
}
总结
| 状态管理方式 | 适用场景 |
|---|---|
remember | UI 生命周期内的临时状态 |
rememberSaveable | 可在屏幕旋转等配置变更后保持状态 |
mutableStateOf | 监听单个变量的状态变化 |
derivedStateOf | 依赖另一个状态计算,避免不必要的重组 |
produceState | suspend function 或 Flow 转 State |
snapshotFlow | State 转 Flow |
collectAsState | Flow 转 State |
LaunchedEffect | 副作用处理(如网络请求) |
rememberCoroutineScope | 处理 CoroutineScope |
rememberUpdatedState | 确保 State 始终保持最新 |