Kotlin:用源码来深入理解 ‘StateFlow和SharedFlow的区别和联系‘

Kotlin:用源码来深入理解 ‘StateFlow和SharedFlow的区别和联系’

在这里插入图片描述

在这篇文章中,我们将深入研究Kotlin中的StateFlow和SharedFlow,以及它们的相似之处和不同之处。我们将通过查看它们的源代码来理解它们的工作原理,这将帮助我们更好地理解它们的用途和优势。

StateFlow

StateFlow是Kotlin中的一个概念,它是一个热Flow,可以存储状态。它的主要特点是始终保持最新的状态值,而且任何时候都可以访问这个状态值。当你观察StateFlow时,你将首先接收到当前的状态值,然后每当状态改变时,你都会收到新的状态值。

StateFlow的源代码如下:
伪源码:

public abstract class StateFlow<out T> : Flow<T> {public abstract val value: Tpublic abstract val replayCache: List<T>
}

在这段代码中,我们可以看到StateFlow有一个value属性,这是当前的状态值。还有一个replayCache属性,它是一个包含最近发出的值的列表。在StateFlow的情况下,这个列表总是包含一个元素,即当前的状态值。

当然实际上的源码是继承自SharedFlow, 但是因为SharedFlow中有个public abstract val replayCache: List<T> 所以就相当于上面的伪源码
实际上的源码:

public interface StateFlow<out T> : SharedFlow<T> {/*** The current value of this state flow.*/public val value: T
}

SharedFlow

SharedFlow也是一个热Flow,但它和StateFlow有一些关键的区别。首先,SharedFlow没有一个固定的当前值。相反,它只是广播它接收到的所有值。其次,SharedFlow可以有一个回放缓存,它是一个包含最近发出的值的列表。这个列表的大小可以在创建SharedFlow时设置。

SharedFlow的源代码如下:

public abstract class SharedFlow<out T> : Flow<T> {public abstract val replayCache: List<T>
}

在这段代码中,我们可以看到SharedFlow只有一个replayCache属性,没有value属性。这反映了SharedFlow和StateFlow的主要区别:SharedFlow没有一个固定的当前值,而StateFlow有。

StateFlow和SharedFlow的联系和区别

StateFlow和SharedFlow都是热Flow,它们都可以广播值给多个观察者。然而,它们在如何处理这些值方面有一些关键的区别。StateFlow始终有一个当前值,而SharedFlow没有。相反,SharedFlow只是广播它接收到的所有值。

另一方面,SharedFlow可以有一个回放缓存,这是一个包含最近发出的值的列表。这个列表的大小可以在创建SharedFlow时设置。而StateFlow的回放缓存总是只包含当前的状态值。

StateFlow的使用示例

让我们看一个StateFlow的使用示例。在这个例子中,我们有一个名为uiState的StateFlow,它保存了UI的状态。

private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState

在这个例子中,我们首先创建了一个MutableStateFlow,它是一个可以改变的StateFlow。然后,我们创建了一个只读的StateFlow,它的值是MutableStateFlow的值。这样,我们可以在内部改变_uiState的值,但外部只能观察uiState的值。

SharedFlow的使用示例

现在让我们看一个SharedFlow的使用示例。在这个例子中,我们有一个名为events的SharedFlow,它用于发送事件。

private val _events = MutableSharedFlow<Event>()
val events: SharedFlow<Event> = _events

在这个例子中,我们首先创建了一个MutableSharedFlow,它是一个可以改变的SharedFlow。然后,我们创建了一个只读的SharedFlow,它的值是MutableSharedFlow的值。这样,我们可以在内部发送事件到_events,但外部只能观察events

StateFlow和SharedFlow的比较

从这两个例子中,我们可以看出StateFlow和SharedFlow的一些关键区别。StateFlow有一个固定的当前值,这个值可以被观察者获取。这使得StateFlow非常适合用于表示状态,如UI状态。

另一方面,SharedFlow没有固定的当前值。相反,它只是广播它接收到的所有值。这使得SharedFlow非常适合用于表示事件,如用户操作。

复杂的StateFlow示例

在这个例子中,我们有一个名为uiState的StateFlow,它保存了UI的状态。我们还有一个名为loadData的函数,它从网络加载数据,并更新uiState

private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiStatesuspend fun loadData() {_uiState.value = UiState.Loadingval data = repository.loadData()_uiState.value = UiState.Success(data)
}

在这个例子中,loadData函数首先将uiState的值设置为Loading,然后加载数据,最后将uiState的值设置为Success。这样,观察者可以观察到uiState的变化,并根据其值来更新UI。

复杂的SharedFlow示例

在这个例子中,我们有一个名为events的SharedFlow,它用于发送事件。我们还有一个名为sendEvent的函数,它发送一个事件到events

private val _events = MutableSharedFlow<Event>()
val events: SharedFlow<Event> = _eventssuspend fun sendEvent(event: Event) {_events.emit(event)
}

在这个例子中,sendEvent函数发送一个事件到events。观察者可以观察到events,并根据接收到的事件来执行相应的操作。

StateFlowSharedFlow的比较

从这两个例子中,我们可以看到StateFlow和SharedFlow在复杂场景下的使用。StateFlow非常适合用于表示可以随时间变化的状态,如UI状态。SharedFlow则非常适合用于表示一次性的事件,如用户操作。

StateFlow和SharedFlow的区别

StateFlow和SharedFlow虽然都是Flow,但它们有一些关键的区别。

  • StateFlow有一个固定的当前值,这个值可以被观察者获取。这使得StateFlow非常适合用于表示状态,如UI状态。

  • SharedFlow没有固定的当前值。相反,它只是广播它接收到的所有值。这使得SharedFlow非常适合用于表示事件,如用户操作。

StateFlow和SharedFlow的使用建议

在选择使用StateFlow还是SharedFlow时,你应该根据你的需求来决定。

  • 如果你需要表示一个可以随时间变化的状态,你应该使用StateFlow。例如,你可以使用StateFlow来表示UI的状态。

  • 如果你需要表示一次性的事件,你应该使用SharedFlow。例如,你可以使用SharedFlow来表示用户操作。

这就是我们对StateFlow和SharedFlow的深入理解。希望这篇文章能帮助你更好地理解和使用Kotlin的Flow。

举例说明

在我们的应用中,我们有一个购物车功能。购物车的内容是一个状态,它随着用户添加或删除商品而变化。我们可以使用StateFlow来表示这个状态。

private val _cart = MutableStateFlow<List<Product>>(emptyList())
val cart: StateFlow<List<Product>> = _cartsuspend fun addProduct(product: Product) {_cart.value = _cart.value + product
}suspend fun removeProduct(product: Product) {_cart.value = _cart.value - product
}

在这个例子中,我们有一个名为cart的StateFlow,它表示购物车的内容。我们还有两个函数addProductremoveProduct,它们分别用于添加商品到购物车和从购物车中删除商品。

另一方面,我们的应用还有一个消息通知功能。当有新消息时,我们需要通知所有的观察者。我们可以使用SharedFlow来实现这个功能。

private val _messages = MutableSharedFlow<Message>()
val messages: SharedFlow<Message> = _messagessuspend fun sendMessage(message: Message) {_messages.emit(message)
}

在这个例子中,我们有一个名为messages的SharedFlow,它用于发送消息。我们还有一个名为sendMessage的函数,它用于发送消息到messages

这就是我们在实际应用中如何使用StateFlow和SharedFlow的例子。希望这些例子能帮助你更好地理解StateFlow和SharedFlow的用途。

感谢阅读, Best Regards!

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

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

相关文章

【五】【C++】类与对象(三)

const只读 在 C 中&#xff0c;const 关键字用于声明一个变量为常量&#xff0c;意味着一旦被初始化之后&#xff0c;它的值就不能被改变。 声明常量&#xff1a; 使用 const 关键字可以声明变量为常量。这意味着这个变量的值不能被修改。 const int MAX_SIZE 100; 指针与…

Quartus生成烧录到FPGA板载Flash的jic文件

简要说明&#xff1a; Altera的FPGA芯片有两种基本分类&#xff0c;一类是纯FPGA&#xff0c;另一类是FPGASoc&#xff08;System on chip)&#xff0c;也就是FPGAHPS&#xff08;Hard Processor System&#xff0c;硬核处理器&#xff09;&#xff0c;对应两种Flash烧录方式&a…

【HTML】自定义属性(data)

自定义属性 data: 的用法&#xff08;如何设置,如何获取) &#xff0c;有何优势&#xff1f; data-* 的值的获取和设置&#xff0c;2种方法: 传统方法 getAttribute() 获取 data- 属性值; setAttribute() 设置 data- 属性值getAttribute() 获取 data- 属性值; setAttribute()…

什么是自动化测试分层?3个层次从高到低又是哪些?

自动化测试分层&#xff0c;可以理解为将测试任务分解为多个层次&#xff0c;并在每个层次中定义特定的测试任务和测试范围&#xff0c;通过这种方式&#xff0c;测试人员可以更好地管理和组织测试工作&#xff0c;确保测试的全面性和准确性。 自动化测试可以分解为3个层次&am…

@ControllerAdvice(实现全局异常、全局参数、请求参数预处理)

近期看到了ControllerAdvice这个注解&#xff0c;本身只是为了看下全局异常处理的&#xff0c;简单了解后发现可以分别与ExceptionHandler、ModelAttribute、InitBinder实现 全局异常、全局参数、请求参数预处理 的功能。 目录 一、全局异常处理二、全局参数处理三、请求参数预…

LPC804开发(11.ADC使用)

1.前言 刚刚研究ADC的时候发现芯片里面还有应该mrt 16位的定时器没有搞&#xff0c;那回头补上吧。下午研究了一下ADC的使用&#xff0c;我也只是能用上&#xff0c;这里我只是抛砖引玉一下吧&#xff0c;有需要的还请各位自行深入探究&#xff0c;我这里讲解的是软件触发模式…

AI工具【OCR 01】Java可使用的OCR工具Tess4J使用举例(身份证信息识别核心代码及信息提取方法分享)

Java可使用的OCR工具Tess4J使用举例 1.简介1.1 简单介绍1.2 官方说明 2.使用举例2.1 依赖及语言数据包2.2 核心代码2.3 识别身份证信息2.3.1 核心代码2.3.2 截取指定字符2.3.3 去掉字符串里的非中文字符2.3.4 提取出生日期&#xff08;待优化&#xff09;2.3.5 实测 3.总结 1.简…

Unity SRP 管线【第九讲:URP 点光源与聚光灯】

文章目录 CPU数据搜集GPU数据使用光照计算 CPU数据搜集 我们只能支持有限数量的其他灯。并将这些灯光数据&#xff08;位置、颜色、阴影强度、方向光光源、灯光遮蔽Probe、灯光层级Mask&#xff09;发送到GPU以供场景中所有物体渲染使用。 //ForwardLights.cs 额外光源数量与…

qt内存自动释放的两种情况

qt内存管理机制 QObject的parent 我们时常能看到QWidget或者其他的控件的构造函数中有一项参数parent&#xff0c;默认值都为NULL&#xff0c;例如&#xff1a; QLineEdit(const QString &contents, QWidget *parent nullptr); QWidget(QWidget *parent nullptr, Qt::…

vue3学习——初始化项目及配置

初始化项目 环境 node 16pnpm 8.0.0 命令 pnpm create vite进行以下选择 &#x1f447; – 项目名 – VUe – Ts – cd/目录 – pnpm run dev 浏览器自动打开 package.json 配置eslint 安装依赖包 pnpm i eslint -D npx eslint --init // 生成配置文件进行以下选择 &a…

【2024】大三寒假再回首:缺乏自我意识是毒药,反思和回顾是解药

2024年初&#xff0c;学习状态回顾 开稿时间&#xff1a;2024-1-23 归家百里去&#xff0c;飘雪送客迟。 搁笔日又久&#xff0c;一顾迷惘时。 我们饱含着过去的习惯&#xff0c;缺乏自我意识是毒药&#xff0c;反思和回顾是解药。 文章目录 2024年初&#xff0c;学习状态回顾一…

vue——实现多行粘贴到table事件——技能提升

最近在写后台管理系统时&#xff0c;遇到一个需求&#xff0c;就是要从excel表格中复制多行内容&#xff0c;然后粘贴到后台系统中的table表格中。 如下图所示&#xff1a;一次性复制三行内容&#xff0c;光标放在红框中的第一个框中&#xff0c;然后按ctrlv粘贴事件&#xff0…

掌上医院预约挂号缴费系统源码,与医院信息系统共享数据,实现在线预约挂号、移动支付、医保支付、检验检查报告查看、门诊病历查询等功能。

随着信息技术的发展和互联网的普及&#xff0c;越来越多的患者开始习惯于通过互联网获取医疗服务。网上预约挂号是近年来开展的一项便民就医服务&#xff0c;旨在缓解看病难、挂号难的就医难题&#xff0c;许多患者为看一次病要跑很多次医院&#xff0c;最终还不一定能保证看得…

MySQL数据控制语言DCL

MySQL数据控制语言DCL 目录 MySQL数据控制语言DCLDCL关键字1.事务事务的四大特性START TRANSACTION&#xff1a;开始事务ROLLBACK&#xff1a;回滚COMMIT&#xff1a;提交事务 2.用户权限CREATE USER&#xff1a;创建新的用户并指定权限DROP USER&#xff1a;删除用户ALTER USE…

深度强化学习(王树森)笔记10

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

LeetCode —— 17. 电话号码的字母组合

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

基于人体姿态的目标追踪实现

文章目录 概要人体姿态识别人体关键点转检测框实时跟踪器概要 这篇博文简单介绍了如何实现基于人体姿态的多目标跟踪算法。主要分为以下几个步骤: 基于FastDeploy实现人体姿态识别;将人体姿态转化为检测框;基于SORT算法实现目标跟踪。人体姿态识别 参考Fastdeploy实现。 模…

Ubuntu系统硬盘分区攻略(磁盘分区、RAID磁盘阵列、RAID阵列、固态硬盘分区、机械硬盘分区、swap分区、swap交换分区)

文章目录 分区需求分区方案分区顺序相关疑问swap分区不是应该放在最后吗&#xff1f;我安装系统分区的时候&#xff0c;上面有available devices&#xff0c;下面有create software raid(md)&#xff0c;我该用哪个&#xff1f;我available devices下面有个893G的固态&#xff…

Selenium自动化测试 —— 模拟鼠标键盘的操作事件

鼠标操作事件 在实际的web产品测试中&#xff0c;对于鼠标的操作&#xff0c;不单单只有click()&#xff0c;有时候还要用到右击、双击、拖动等操作&#xff0c;这些操作包含在ActionChains类中。 ActionChains类中鼠标操作常用方法&#xff1a; 首先导入ActionChains类&#…

Python OpenCV实现图片像素区域缩放

Python OpenCV实现图片像素区域缩放 前言项目安装OpenCV和Pillow思路代码编写 前言 遇到一个要将大量图片缩放成统一规格的难题&#xff0c;并且这些图片周围还有很多空白像素&#xff0c;所以用Python实现一下。 项目 安装OpenCV和Pillow pip install opencv-python pip …