kotlin 中的flow sharedFlow 完整教程
目录
- 一 sharedFlow是什么
- ✅ SharedFlow 是什么?
- ✅ 常见使用场景
- 1. 一次性 UI 事件
- 2. 流式通知
- 3. 替代 LiveData<Event>android; 解决重复消费问题
- ✅ 在公司项目中,SharedFlow 的典型用法
- 示例:登录成功后跳转 + 弹出 Toast
- ✅ 与其他 Flow 类型的对比
- ✅ 总结一句话:
- 二 sharedFlow如何处理背压的?
- ✅ 1. SharedFlow 是如何处理被压的(Backpressure)android?
- ✅ 2. replay = 2, extraBufferCapacity = 5 的含义
- ✅ 3. onBufferOverflow = DROP_OLDEST / DROP_LATEST / SUSPEND 是什么?
- ✅ 总结一句话:
一 sharedFlow是什么
SharedFlow
是 Kotlin 协程中 Flow
的一种 热流(Hot Flow),用于在多个订阅者之间 共享事件或数据流。它适合处理 一次性事件(如导航、弹窗、Toast、刷新通知等),而不是持续状态。
✅ SharedFlow 是什么?
SharedFlow
是 Flow
的一种扩展,具备以下特点:
特性 | 描述 |
---|---|
热流 | 一旦被触发,即使没人监听也会发出 |
多订阅者 | 所有活跃订阅者都能收到事件 |
不保留最新值(除非设置 replay) | 不像 StateFlow 那样始终有个当前值 |
可配置 buffer 和回放(replay) | 控制事件是否缓存、丢弃或排队 |
它本质上是一个“事件广播器”。
✅ 常见使用场景
1. 一次性 UI 事件
- Toast 弹窗
- SnackBar 提示
- 导航跳转
- 关闭页面
- 对话框展示/取消
这些事件都是“一次性的”,不需要保存状态,也不该重复触发,因此适合 SharedFlow
。
sealed class UiEvent { data class ShowToast(val message: String) : UiEvent() object NavigateToHome : UiEvent() }
// ViewModel 中 private val _uiEvent = MutableSharedFlow<UiEvent>() val uiEvent = _uiEvent.asSharedFlow() fun loginSuccess() { viewModelScope.launch { _uiEvent.emit(UiEvent.NavigateToHome) } }
// Fragment 中 lifecycleScope.launchWhenStarted { viewModel.uiEvent.collect { event -> when (event) { is UiEvent.ShowToast -> showToast(event.message) is UiEvent.NavigateToHome -> navigate() } } }
2. 流式通知
- 通知其他模块刷新数据
- 数据拉取完成通知页面更新
- ViewModel 向 UI 发信号
3. 替代 LiveData<Event>编程客栈 解决重复消费问题
传统用 LiveData<Event<T>>
或 SingleLiveEvent
处理一次性事件,代码复杂、不优雅,而 SharedFlow
是官方推荐的替代方案。
✅ 在公司项目中,SharedFlow 的典型用法
层 | 使用方式 |
---|---|
ViewModel | 使用 MutableSharedFlow 发送事件 |
UI(Activity/Fragment) | 使用 collect 监听事件,做 UI 响应 |
工具类/中间层 | 也可以用于广播通知、分发事件 |
示例:登录成功后跳转 + 弹出 Toast
// ViewModel val eventFlow = MutableSharedFlow<UiEvent>() suspend fun login(username: String, pwd: String) { if (doLogin(username, pwd)) { eventFlow.emit(UiEvent.ShowToast("登录成功")) eventFlow.emit(UiEvent.NavigateHome) } }
✅ 与其他 Flow 类型的对比
类型 | 是否热流 | 是否可变 | 是否保留值 | 场景 |
---|---|---|---|---|
Flow | ❌ 冷流 | ❌ | ❌ | 一次性数据流 |
SharedFlow | ✅ 热流 | ✅ | ❌(可设置 replay) | 一次性事件广播 |
StateFlow | ✅ 热流 | ✅ | ✅(必须初始值) | 状态管理(UI 状态、进度等) |
✅ 总结一句话:
SharedFlow
= Kotlin 中处理一次性事件的推荐工具,适合在 ViewModel → UI 层传递 Toast、导航、弹窗等短暂行为,比 LiveData
更现代、可控。
二 sharedFlow如何处理背压的?
✅ 1. SharedFlow 是如何处理被压的(Backpressure)?
SharedFlow
是 热流(hot stream),意味着数据会立即发出,而不会像 Flow
那样等待订阅者 collect。这也就意味着:
- 如果发射得太快(比如连续多次 emit)http://www.devze.com
- 而订阅者还没来得及 collect
- 数据就可能被丢弃,或缓存起来等待
这就需要一个“缓存策略”来决定怎么处理这些“来不及处理”的数据 —— 这就是 SharedFlow 的 buffer 和 溢出策略(onBufferOverflow)。
✅ 2. replay = 2, extraBufferCapacity = 5 的含义
val sharedFlow = MutableSharedFlow<Int>( replay = 2, extraBufferCapacity = 5 )
这两者分别控制了两块缓存区域:
参数 | 含义 |
---|---|
replay = 2 | 每个新订阅者会 立刻收到前 2 条值(即“回放值”) |
extraBufferCapacity = 5 | 除了 replay 缓冲python区之外,还允许临时缓存 最多 5 条数据 |
总缓冲区大小 = replay + extraBufferCapacity
即上面的配置,总共可以缓冲 最多 7 条数据。
这意味着在没有 collect 的情况下,可以最多 emit 7 条数据不会失败或丢失。
✅ 3. onBufferOverflow = DROP_OLDEST / DROP_LATEST / SUSPEND 是什么?
这是控制当 缓冲区已满时,继续 emit 会怎么处理的策略。
支持的策略:
策略名 | 解释 |
---|---|
DROP_OLDEST | 丢掉最早 emit 的一条数据(先进先出) |
DROP_LATEST | 丢掉新发射的数据(调用的 emit) |
SUSPEND (默认) | 挂起 emit 调用,直到 buffer 有空间(安全但可能阻塞) |
示例说明:
val flow = MutableSharedFlow<Int>( replay = 1, extraBufferCapacity = 2, onBufferOverflow = BufferOverflow.DROP_OLDEST )
此时总 buffer 是 3 条:
- 如果连续 emit 第 1、2、3 条 → 都能进 buffer。
- 如果 emit 第 4 条时还没人 collect → buffer 满了。
DROP_OLDEST
策略:会把 第 1 条值移除,保留 2、3、4。
emit() 和 tryEmit() 的区别:
emit()
是 挂起函数,可能会suspend
(如果 buffer 满且策略是SUSPEND
)。tryEmit()
是 非挂起,返回true/false
表示是否成功发射。
✅ 总结一句话:
配置项 | 意义 |
---|---|
replay | 新订阅者能收到多少“历史值” |
extraBufferCapacity | 在未 collect 情况下,能暂存多少新值 |
onBufferOverflow | 当缓存已满,是否丢老的、丢新的,或挂起等候 |
总缓存 | replay + extraBufferCapacity 条数据 |
到此这篇关于kotlin 中的flow sharedFlow 完整教程的文章就介绍到这了,更多相关kotlin sharedFlow内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论