前言

以下内容为学习笔记,不保证内容的准确性!

虽然Jetpack Compose的状态管理很容易让人血压升高,但如果用不好状态管理会让人血压更高。

Flow与StateFlow

下面表格来自DeepSeek:

特性 Flow StateFlow
冷流 vs 热流 冷流(Cold Stream) 热流(Hot Stream)
数据发射时机 每次调用 collect 时从头开始发射数据 持有当前值,立即发送给新收集者
适用场景 异步数据流(如网络请求、数据库查询) UI 状态管理(如主题、登录状态)
值的保留 无状态,不保留数据 始终持有最新值
值的更新触发条件 每次 collect 都会触发数据发射 仅当新值与旧值不同时触发更新(equals 比较)

Flow转StateFlow

1
2
3
4
5
val stateFlow: StateFlow<Data> = someFlow.stateIn(
scope = viewModelScope, //使用ViewModel的作用域
started = SharingStarted.WhileSubscribed(5000), //当有活跃订阅者时启动(也可以使用SharingStarted.Lazily)
initialValue = Data() //初始值
)

使用

两者均可以通过collectAsStateWithLifecycle()或者collectAsState()转换为State供Compose UI使用。

如果需要在收集时处理数据,也可以使用collect():

1
2
3
stateFlow.collect{item->
//对接收的item进行处理
}

需要注意的是,当使用collect后会持续订阅,因此只需订阅一次即可。在Compose中可以使用LaunchedEffect(Unit)来进行订阅操作,LaunchedEffect(Unit)在整个生命周期中只会执行一次,适合于这种只需执行一次的代码。当然,重复执行collect进行订阅也没问题,stateFlow会自动停止之前的订阅然后重新开始新的订阅。

StateFlow与State

设计目的

由DeepSeek分析:

  • State

  • 专为 Compose 设计,用于在可组合函数(Composable)中跟踪和响应局部 UI 状态的变化。

  • 通过 mutableStateOf 创建,当值变化时,会自动触发 UI 重组(Recomposition)。

  • 适用于简单的 UI 状态管理,例如按钮的选中状态、文本输入值等。

  • StateFlow

  • 属于 Kotlin 的响应式流(Flow)的一部分,用于在应用的不同层之间共享状态(如 ViewModel 到 UI 层)。

  • 需要手动通过 collect 或 collectAsState 订阅数据流,适合处理跨组件或跨生命周期的状态共享

  • 更适用于复杂业务逻辑的状态管理,例如从网络请求或数据库加载数据。

适用场景

State比较适合UI内的临时变量,如TextField的text的值,Switch的checked的值等

因为Compose设计为单向数据流,所以需要使用State来保存重组前上一次的值。

StateFlow适合于共享状态,特别是在ViewModel中供多个UI控件进行观察。

并且使用rememberState在退出组合时数据将被丢弃,而StateFlow的生命周期通常跟随ViewModel,在退出组合时数据不会出现丢失。

有点像传统Android xml开发里将数据保存在ViewModel中防止因切换主题暗色模式或者切换横竖屏而导致UI状态丢失。

使用

State结合remembermutableStateOf,就像普通变量一样使用即可

StateFlow则需要使用collectcollectAsState()订阅状态:

1
val stateFlow by ViewModel.stateFlow.collectAsState()