当前位置: 首页 > article >正文

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 条数据

相关文章:

kotlin 02flow-sharedFlow 完整教程

一 sharedFlow是什么 SharedFlow 是 Kotlin 协程中 Flow 的一种 热流&#xff08;Hot Flow&#xff09;&#xff0c;用于在多个订阅者之间 共享事件或数据流。它适合处理 一次性事件&#xff08;如导航、弹窗、Toast、刷新通知等&#xff09;&#xff0c;而不是持续状态。 ✅ …...

CentOS网络之network和NetworkManager深度解析

文章目录 CentOS网络之network和NetworkManager深度解析1. CentOS网络服务发展历史1.1 传统network阶段&#xff08;CentOS 5-6&#xff09;1.2 过渡期&#xff08;CentOS 7&#xff09;1.3 新时代&#xff08;CentOS 8&#xff09; 2. network和NetworkManager的核心区别3. ne…...

【AI】模型与权重的基本概念

在 ModelScope 平台上&#xff0c;「模型」和「权重」的定义与工程实践紧密结合&#xff0c;理解它们的区别需要从实际的文件结构和加载逻辑入手。以下是一个典型 ModelScope 模型仓库的组成及其概念解析&#xff1a; 1. ModelScope 模型仓库的典型结构 以 deepseek-ai/deepse…...

设计模式-基础概念学习总结(继承、多态、虚方法、方法重写)

概念使用例子的方式介绍&#xff08;继承&#xff0c;多态&#xff0c;虚方法&#xff0c;方法重写&#xff09;&#xff0c;实现代码python 1. 继承&#xff08;Inheritance&#xff09; 概念&#xff1a;子类继承父类的属性和方法&#xff0c;可以直接复用父类的代码&#…...

2025年小程序DDoS与CC攻击防御全指南:构建智能安全生态

2025年&#xff0c;小程序已成为企业数字化转型的核心载体&#xff0c;但随之而来的DDoS与CC攻击也愈发复杂化、智能化。攻击者利用AI伪造用户行为、劫持物联网设备发起T级流量冲击&#xff0c;甚至通过漏洞窃取敏感数据。如何在高并发业务场景下保障小程序的稳定与安全&#x…...

当当狸智能天文望远镜 TW2 | 用科技触摸星辰,让探索触手可及

当科技邂逅星空&#xff0c;每个普通人都能成为宇宙的追光者 伽利略用望远镜揭开宇宙面纱的 400 年后&#xff0c;当当狸以颠覆传统的设计&#xff0c;让天文观测从专业领域走入千家万户。当当狸智能天文望远镜 TW2&#xff0c;重新定义「观星自由」—— 无需专业知识&#xff…...

QT实现曲线图缩放、拖拽以及框选放大

.h文件 protected: void saveAxisRange();void wheelEvent(QWheelEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private:QPoint m_…...

C# | 基于C#实现的BDS NMEA-0183数据解析上位机

以下是一个基于C#实现的BDS NMEA-0183数据解析上位机的示例代码,包含基础功能和界面: using System; using System.Collections.Generic; using System.IO.Ports; using System.Windows.Forms; using System.Drawing; using System.Globalization;namespace BDS_NMEA_Viewer…...

科学发现 | 源于生活的启示与突破计划的创新

注&#xff1a;本文为“科学发现”相关文章合辑。 略作重排&#xff0c;未全整理。 哪些重大科学发现&#xff0c;来自生活的启示 ︱ 科学史 2020/10/29 导读 好奇心是最好的向导和老师。 撰文 | 陈敬全&#xff08;东华大学人文学院教授&#xff09; 英国进化论者赫胥黎…...

【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?

文章目录 一、添加数据二、绘制形状三、裁剪格网和经纬网一、添加数据 打开软件,添加配套实验数据包中0145.rar中的影像数据,如下图所示: 二、绘制形状 1. 在数据视图中,使用绘图 工具条上的新建圆工具 可创建一个椭圆,使其包含要在该数据框中显示的数据范围。 修改椭圆…...

网络安全防火墙技术有哪些?网络防火墙的主要作用

网络安全防火墙技术有哪些?网络防火墙的主要作用 网络安全防火墙技术是保护网络免受未经授权访问和攻击的关键工具。以下是常见的防火墙技术及其主要作用&#xff1a; 一、网络安全防火墙技术分类 包过滤防火墙&#xff08;Packet Filtering Firewall&#xff09; 原理&#x…...

数据集-目标检测系列- 印度人脸 检测数据集 indian face >> DataBall

数据集-目标检测系列- 印度人脸 检测数据集 indian face >> DataBall DataBall 助力快速掌握数据集的信息和使用方式。 贵在坚持&#xff01; * 相关项目 1&#xff09;数据集可视化项目&#xff1a;gitcode: https://gitcode.com/DataBall/DataBall-detections-100s…...

Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.

版本: 原因 在 Dart Sass 3.0.0 中, @import 规则将被弃用,推荐使用 @use 和 @forward 规则来替代。 1.@use替代@import @use 规则允许你引入其他 Sass 文件中的变量、混合器和函数,并且可以避免命名冲突。 示例: style.scss @use variables;body {color: variables.$pr…...

通过CIDR推出子网掩码和广播地址等

写在前面 不知道你遇到过这种面试题没&#xff0c;给你CIDR&#xff0c;让你推理子网掩码等信息。如果你不会&#xff0c;那本文刚好适合你。 1&#xff1a;一个面试题16.158.165.91/22 这个 CIDR。求一下这个网络的第一个地址、子网掩码和广播地址。 一般如果你对CIDR知识有…...

【工具教程】批量提取PDF指定内容并重命名,PDF文档根据指定识别文字改名,基于java的实现方案

物流单据处理​​&#xff1a;每天处理大量发货单PDF&#xff0c;提取订单编号、发货方信息等关键字段重命名文件 合同管理​​&#xff1a;从合同PDF中提取合同编号、签署方名称等作为文件名 ​​学术论文整理​​&#xff1a;根据论文标题或作者信息重命名PDF文件 财务票据…...

std::iota(C++)

std::iota 1. 概述2. 函数原型3. 使用示例示例 1&#xff1a;填充 vector<int>示例 2&#xff1a;从非零起始值开始 4. 应用场景5. 注意事项6. 与其它算法比较小结 1. 概述 std::iota 定义在头文件 中&#xff0c;C11 起引入。 它用于向前迭代器区间依次填入连续递增的数…...

【IP101】图像特征提取技术:从传统方法到深度学习的完整指南

&#x1f31f; 特征提取魔法指南 &#x1f3a8; 在图像处理的世界里&#xff0c;特征提取就像是寻找图像的"指纹"&#xff0c;让我们能够识别和理解图像的独特性。让我们一起来探索这些神奇的特征提取术吧&#xff01; &#x1f4da; 目录 基础概念 - 特征的"体…...

苍穹外卖(用户下单、订单支付)

用户下单、订单支付 导入地址簿功能代码 接口设计 数据库设计&#xff08;address_book表&#xff09; 代码导入 功能测试 用户下单 接口设计 数据库设计 订单表 orders 订单明细表 order_detail 代码开发 根据用户下单接口的参数设计DTO 根据用户下单接口的…...

数据结构-非线性结构-二叉树

概述 /** * 术语 * 根节点&#xff08;root node&#xff09;&#xff1a;位于二叉树顶层的节点&#xff0c;没有父节点。 * 叶节点&#xff08;leaf node&#xff09;&#xff1a;没有子节点的节点&#xff0c;其两个指针均指向 None 。 * 边&#xff08;edge&#xff09;&…...

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】3.2 缺失值检测与处理(NULL值填充/删除策略)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 缺失值检测与处理全攻略&#xff1a;NULL值填充与删除策略实战3.2 缺失值检测与处理3.2.1 缺失值类型与业务影响3.2.1.1 缺失值的三种形态3.2.1.2 业务影响分级 3.2.2 缺失值…...

2025年渗透测试面试题总结-某步在线面试(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、操作系统相关问题总结与分析及扩展回答 1. Linux命令熟悉度 2. 查看进程的命令 3. 查看网络进程…...

Java后端程序员学习前端之JavaScript

1.什么是JavaScript 1.1.概述 JavaScript是一门世界上最流行的脚本语言javaScript 一个合格的后端人员&#xff0c;必须要精通JavaScript 1.2.历史 JavaScript的起源故事-CSDN博客 2.快速入门 2.1.引入JavaScript 1.内部标签 <script>//.......</script> --…...

ARM Linux 设备树

Linux 设备驱动开发详解&#xff1a;基于最新的Linux 4.0内核, 机械工业出版社, 宋宝华, 2015 1. 设备树的起源 • 背景: ARM架构中大量板级代码冗余&#xff0c;硬编码在mach-xxx目录&#xff0c;设备树&#xff08;Device Tree&#xff09;引入结构化描述硬件。 • 目的: 减…...

uniapp-商城-43-shop 后台管理 页面

后台管理较为简单&#xff0c;主要用于后台数据的管理&#xff0c;包含商品类别和商品信息&#xff0c;其实还可以扩展到管理用户等等 1、后台首页 包含 分类管理 商品管理 关于商家等几个栏目 主要代码&#xff1a; <template><view class"manage">…...

kotlin JvmName注解的作用和用途

1. JvmName 注解的作用 JvmName 是 Kotlin 提供的一个注解&#xff0c;用于在编译为 Java 字节码时自定义生成的类名或方法名。 作用对象&#xff1a; 文件级别&#xff08;整个 .kt 文件&#xff09;函数、属性、类等成员 主要用途&#xff1a; 控制 Kotlin 编译后生成的 JV…...

Mac 平台 字体Unicode范围分析器

字体Unicode范围分析器 #include <CoreText/CoreText.h> // CoreText框架头文件&#xff0c;用于字体处理 #include <CoreFoundation/CoreFoundation.h> // CoreFoundation框架头文件 #include <stdio.h> // 标准输入输出 #include…...

【C++游戏引擎开发】第30篇:物理引擎(Bullet)—软体动力学系统

一、软体动力学理论体系 1.1 连续体力学基础 1.1.1 变形梯度张量 物体运动可描述为映射函数: x = ϕ ( X , t ) \mathbf{x} = \phi(\mathbf{X},t) x...

vue2 结合后端预览pdf 跨域的话就得需要后端来返回 然后前端呈现

<el-button :loading"pdfIslock" v-if"isPDFFile(form.pic)" type"primary" style"margin: 15px 0" click"previewPDF(form.pic)"> 预览pdf </el-button>//npm install pdfjs-dist //如果没有就得先安装import …...

什么是 HSQLDB?

大家好&#xff0c;这里是架构资源栈&#xff01;点击上方关注&#xff0c;添加“星标”&#xff0c;一起学习大厂前沿架构&#xff01; Java开发人员学习Java数据库连接&#xff08;JDBC&#xff09;的最简单方法是试验HyperSQL数据库&#xff08;又名HSQLDB&#xff09;。 …...

AI时代企业应用系统架构的新思路与CIO变革指南

作为制造企业CIO&#xff0c;我们看问题需要有前瞻性&#xff0c;AI时代企业应用系统架构需要进行全面转型。 一、新思想与新技术 1. 核心新思想 可视化开发AI的融合模式&#xff1a;不再只依赖纯代码开发或传统低代码&#xff0c;而是两者结合&#xff0c;通过AI理解自然语…...