# 前言

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

虽然 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()