kotlin 02flow-sharedFlow 完整教程

一 sharedFlow是什么

SharedFlow 是 Kotlin 协程中 Flow 的一种 热流(Hot Flow),用于在多个订阅者之间 共享事件或数据流。它适合处理 一次性事件(如导航、弹窗、Toast、刷新通知等),而不是持续状态。


✅ SharedFlow 是什么?

SharedFlowFlow 的一种扩展,具备以下特点:

特性描述
热流一旦被触发,即使没人监听也会发出
多订阅者所有活跃订阅者都能收到事件
不保留最新值(除非设置 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)
  • 而订阅者还没来得及 collect
  • 数据就可能被丢弃,或缓存起来等待

这就需要一个“缓存策略”来决定怎么处理这些“来不及处理”的数据 —— 这就是 SharedFlow 的 buffer溢出策略(onBufferOverflow)


✅ 2. replay = 2, extraBufferCapacity = 5 的含义

val sharedFlow = MutableSharedFlow<Int>(replay = 2,extraBufferCapacity = 5
)

这两者分别控制了两块缓存区域:

参数含义
replay = 2每个新订阅者会 立刻收到前 2 条值(即“回放值”)
extraBufferCapacity = 5除了 replay 缓冲区之外,还允许临时缓存 最多 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 条数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/79823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模拟开发授权平台

这次只是实现应用的curd和公私钥的校验以及第三方的通知dmeo项目&#xff0c;大家可以拓开视野来编写 进入主题 项目链接&#xff1a;桌角的眼镜/develop_auth_platform 直接下拉并运行就行 回调应用代码在test包中 回调应用测试代码 package mainimport ("encoding/…

STM32 USART串口

一、通信接口 二、串口通信 串口是一种应用十分广泛的通讯接口&#xff0c;串口成本低、容易使用、通信线路简单&#xff0c;可实现两个设备的互相通信单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信&#xff0c;极大地扩展了单片机的应用…

uniapp开发06-视频组件video的使用注意事项

uniapp开发-视频组件video的使用注意事项&#xff01;实际项目开发中&#xff0c;经常会遇到视频播放的业务需求。下面简单讲解一下&#xff0c;uniapp官方提供的视频播放组件video的常见参数和实际效果。 1&#xff1a;先看代码&#xff1a; <!--视频组件的使用展示-->…

【爬虫】微博热搜机

第一个下面一点&#xff1a; js代码&#xff1a; const n require("crypto-js");let s n.SHA1(n.enc.Utf8.parse("tSdGtmwh49BcR1irt18mxG41dGsBuGKS")) , a n.enc.Hex.parse(s.toString(n.enc.Hex).substr(0, 32));function h(t) {let e (i t Stri…

软考 系统架构设计师系列知识点之杂项集萃(51)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;50&#xff09; 第80题 设三个煤场A1、A2、A3分别能供应煤7、12、11万吨&#xff0c;三个工厂B1、B2、B3分别需要10、10、10万吨&#xff0c;从各煤场到各工厂运煤的单价&#xff08;百元/吨&…

npm,yarn,pnpm,cnpm,nvm,npx包管理器常用命令

前端比较主流的包管理器主要有三个npm&#xff0c;yarn&#xff0c;pnpm 多层级依赖&#xff0c;通常发生在依赖之间存在复杂的版本要求时 包 A 依赖于包 B1.0.0 包 B 依赖于包 C2.0.0 另一个包 D 也依赖于 C3.0.0 一、NPM (Node Package Manager) https://www.npmjs.cn/…

科普简洁版:同态加密——密码学的未来瑰宝

文章目录 一、同态加密的基本概念1.1 什么是同态加密1.2 同态加密的数学本质1.3 同态加密的类型 二、主要同态加密方案详解2.1 ElGamal加密2.2 Paillier加密2.3 Gentry的完全同态加密方案2.4 BGV方案2.5 BFV方案2.6 CKKS方案 三、同态加密的关键技术3.1 噪声管理技术3.2 多项式…

力扣第448场周赛

赛时成绩如下: 这应该是我力扣周赛的最好成绩了(虽然还是三题) 1. 两个数字的最大乘积 给定一个正整数 n。 返回 任意两位数字 相乘所得的 最大 乘积。 注意&#xff1a;如果某个数字在 n 中出现多次&#xff0c;你可以多次使用该数字。 示例 1&#xff1a; 输入&#xff1…

(一)Modular Monolith Architecture(项目结构/.net项目初始化/垂直切片架构)

文章目录 项目地址一、项目结构1.1 Modules1. Events 模块2. Users 模块3. Ticketing 模块4. Attendance 模块1.2 数据库模块1.3 模块架构选择1. 全是Clean Architecture2. 分别使用不同的架构二、初始化项目2.1 本地创建项目结构1. 创建空的solution2. 添加基础配置3. 创建git…

Java常用组件之Redis经典面试题(一)

大家好&#xff0c;今天为大家带来Java项目中&#xff0c;几乎必不可少的组件之一-Redis的一些常见面试题&#xff0c;帮忙近期需要面试的朋友们来一个理论基础突击&#xff01; 一、数据类型 1.Redis的常用数据类型有哪些 ? 难易程度&#xff1a;☆☆☆ 出现频率&#xff1a;…

2025.5.4总结

今天去光谷步行街逛了一下&#xff0c;感觉熟悉又陌生&#xff0c;说熟悉是因为初二的时候来过武汉光谷&#xff0c;尽管过去了8年时间&#xff0c;但丝毫不影响标志性建筑的存在&#xff0c;也陌生是商场的建筑风格真实气派&#xff0c;感觉进入了一座城堡&#xff0c;在里面都…

神经网络在专家系统中的应用:从符号逻辑到连接主义的融合创新

自人工智能作为一个学科面世以来&#xff0c;关于它的研究途径就存在两种不同的观点。一种观点主张对人脑的结构及机理开展研究&#xff0c;并通过大规模集成简单信息处理单元来模拟人脑对信息的处理&#xff0c;神经网络是这一观点的代表。关于这方面的研究一般被称为连接机制…

Doo全自动手机壳定制系统

Doo全自动手机壳定制系统 项目概述 Doo全自动手机壳定制系统是一个完整的手机壳定制解决方案&#xff0c;支持多端应用&#xff0c;包括服务端、客户端、管理后台等多个组件。系统采用现代化的技术栈&#xff0c;提供完整的手机壳定制、订单管理、用户管理等功能。 目录结构…

PageOffice在线打开word文件,并实现切换文件

本示例关键代码的编写位置&#xff0c;请参考“PageOffice 开发者中心-快速起步–开始 - 快速上手”里您所使用的开发语言框架的最简集成代码 注意 本文中展示的代码均为关键代码&#xff0c;复制粘贴到您的项目中&#xff0c;按照实际的情况&#xff0c;例如文档路径&#xff…

Webug4.0靶场通关笔记12- 第17关 文件上传之前端拦截(3种方法)

目录 一、文件上传前端拦截原理 二、第17关 文件上传(前端拦截) 1.打开靶场 2.构造php脚本 3.源码分析 &#xff08;1&#xff09;js源码 &#xff08;2&#xff09;服务器源码 &#xff08;3&#xff09;总结 4.渗透实战 &#xff08;1&#xff09;禁用js法 &#…

高性能 WEB 服务器 Nginx:多虚拟主机实现!

Nginx 配置多虚拟主机实现 多虚拟主机是指在一台 Nginx 服务器上配置多个网站 在 Nginx 中&#xff0c;多虚拟主机有三种实现方式&#xff1a; 基于IP地址实现多虚拟主机 基于端口号实现多虚拟主机 基于域名实现多虚拟主机 1 基于域名实现多虚拟主机 在 Nginx 中配置多个…

网星安全AWS攻防方案,重磅发布!

AWS介绍 AWS&#xff08;Amazon Web Services&#xff09; 是 Amazon 提供的云计算平台&#xff0c;提供了广泛的云服务&#xff0c;包括计算、存储、数据库、网络、安全、人工智能、大数据处理等功能&#xff0c;帮助企业和开发者构建、部署和管理应用程序。AWS 是全球最大的…

qt的containers里的QToolBox和QTabWidget

Tool Box是一个多层次的折叠面板&#xff0c;通常用于组织多个可展开/折叠的面板组&#xff0c;每个面板有一个标题栏&#xff0c;用户点击标题栏可以展开或收起内容区域。比如设置界面中的分类选项&#xff0c;每个分类可以展开查看详细内容。这样能节省空间&#xff0c;让界面…

【神经网络与深度学习】深度学习中的生成模型简介

深度学习中的生成模型 openai 的一个古早介绍 引言 深度学习中的生成模型能够学习数据分布并生成新数据&#xff0c;在人工智能的多个领域中都有重要应用。不同类型的生成模型在原理和结构上各有特点&#xff0c;适用于不同的任务&#xff0c;如图像生成、文本生成和时间序列…

js获取明天日期、Vue3大菠萝 Pinia的使用

直接上代码 const today new Date(2019, 2, 28) const finalDate new Date(today) finalDate.setDate(today.getDate() 3)console.log(finalDate) // 31 March 2019 安装 yarn add pinia # or with npm npm install pinia创建第一个store仓库 1、在src目录下创建store目录…