渐进式编程课
KMP 目录
第 45 课2026.09.02

避免把连续两次相同操作误当成同一份状态。

第 45 课:状态流与事件流的语义选择

  • 日期:2026-09-02
  • 课程序号:第 45 课
  • 知识点:StateFlow 相等合并与 SharedFlow 重放

用途

避免把连续两次相同操作误当成同一份状态。

核心概念

  • StateFlow 始终有当前值,相等值不会再次通知,慢订阅者可能跳过中间状态。
  • SharedFlow 可以重复发送相等值,但 replay=0 不向后来订阅者补发历史;它不是持久事件队列。
  • 需要当前状态选 stateIn;需共享事件时按消费契约选择 shareIn 的 replay。

最小代码或操作示例

kotlin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.shareIn

fun shareCount(source: Flow<Int>, scope: CoroutineScope): StateFlow<Int> =
    source.stateIn(scope, SharingStarted.WhileSubscribed(), 0)

fun shareClicks(source: Flow<String>, scope: CoroutineScope): SharedFlow<String> =
    source.shareIn(scope, SharingStarted.WhileSubscribed(), replay = 0)

3~5 分钟练习

判断“当前收藏数量”和“连续两次相同按钮点击”分别更适合哪种流;晚订阅者是否应收到旧点击?

参考答案

kotlin
// 当前收藏数量:StateFlow,始终提供当前状态。
// 两次相同点击:SharedFlow 可表达重复事件。
// replay=0:晚订阅者不收到旧点击;无订阅者时也不保证事件保留。
// 若要求不丢事件,需另行设计持久化和确认消费机制。

与上一课的联系

上一课学习 shareIn,第 34 课已学习 stateIn;本课新增相等值与晚订阅行为的选择依据。

参考资料