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

news2024/11/16 9:21:03

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

在这里插入图片描述

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

StateFlow

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

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

public abstract class StateFlow<out T> : Flow<T> {
    public abstract val value: T
    public 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> = _uiState

suspend fun loadData() {
    _uiState.value = UiState.Loading
    val 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> = _events

suspend 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>> = _cart

suspend 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> = _messages

suspend fun sendMessage(message: Message) {
    _messages.emit(message)
}

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

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

感谢阅读, Best Regards!

免责声明

  1. 本文内容及信息,部分或全部可能经由人工智能技术协助编写或完全由AI生成。我已尽力确保这些生成内容的准确性和合法性,然而鉴于人工智能技术固有的局限性,仍可能出现不准确陈述、错误信息或与其他来源相似的内容。

  2. 对于任何读者在阅读过程中发现的问题,包括但不限于涉嫌抄袭、不实或误导性的信息,请及时私信我进行反馈,我会尽快对相关问题进行核实,并作出必要的修正或删除。

  3. 在此明确声明,我所提供的所有可能涉及AI生成的文章和信息,其目的在于知识分享、学习探讨及提供参考,并不能代表我个人在每项具体观点上的详尽研究、深度分析或直接推荐。读者在采纳、引用或应用其中的观点时,应当结合实际情况与其它可靠资料进行独立判断,并自行承担相应责任。

  4. 敬请各位读者,在将我发布的AI生成内容作为决策依据时,充分认识到潜在的局限性,并对此类信息进行进一步的验证和核实。

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

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

相关文章

力扣经典题:用队列表示栈

1. 基本思路&#xff1a;栈具有先入后出的性质&#xff0c;队列具有先入先出的性质&#xff0c;所以栈的栈顶元素就是队的队尾元素&#xff0c;第二个函数要求移除并返回栈顶元素&#xff0c;要满足两个要求&#xff1a;其一是要保证除栈顶外的其它元素可查&#xff0c;二是要…

nodejs+vue+ElementUi高校创业项目申报系统w6f1g

此系统设计主要采用的是nodejs语言来进行开发&#xff0c;采用vue框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安全性…

泰迪智能科技大模型微调项目训练营已开营

泰迪智能科技大模型微调项目训练营开营 跟张良均老师学大数据人工智能 项目一&#xff1a;医疗诊疗对话意图识别 项目二&#xff1a;中医问答系统 项目三&#xff1a;某平台股票评论情感识别 学习流程&#xff1a; 项目一&#xff1a;医疗诊疗对话…

github单文件下载——DownGit

记录一下一个好用的网站&#xff0c;支持github中某一特定文件夹下文件的下载 选择一个合适的梯子&#xff0c;访问Downgit网址 https://minhaskamal.github.io/DownGit/#/home 将所需网站连接粘贴到这里&#xff0c;点击download即可

【软考设计师笔记】计算机系统基础知识

&#x1f413; 计算机系统组成 计算机系统是由硬件和软件组成的&#xff0c;它们协同工作来运行程序。计算机的基本硬件系统由 运算器、控制器、存储器、输入设备和输出设备5大部件组成。运算器、控制器等部件被集成 在一起统称为中央处理单元&#xff08;Central Processing …

第8章 python深度学习——波斯美女

第8章 生成式深度学习 本章包括以下内容&#xff1a; 使用 LSTM 生成文本 实现 DeepDream 实现神经风格迁移 变分自编码器 了解生成式对抗网络 人工智能模拟人类思维过程的可能性&#xff0c;并不局限于被动性任务&#xff08;比如目标识别&#xff09;和大多数反应性任…

Linux进程详解

如有错误或有补充&#xff0c;以及任何的改进意见&#xff0c;请在评论区留下您的高见&#xff0c;同时文中给出大部分示例 即是您暂时无法在Linux中查看&#xff0c;您也可以知道各种操作的功能以及输出 如果觉得本文写的不错&#xff0c;不妨点个赞&#xff0c;收藏一下&am…

基于ssm的法律咨询系统(有报告)。Javaee项目,ssm项目。

演示视频&#xff1a; 基于ssm的法律咨询系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Sp…

mybatisplus-多数据源配置

1. 流程 pom文件yml配置多数据源具体服务添加注解DS(“***”) 1.pom文件 <!--mybatis plus 起步依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</vers…

292. Nim Game(Nim 游戏)

题目描述 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。 你们轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。 假设你们每一步都是最优解。请编写一个函数…

生成式AI应用开发参考架构

人机交互正在迅速经历软件开发在过去二十年中从未见过的巨大范式转变。 从传统的基于规则的系统到复杂的生成人工智能 (GAI) 模型&#xff0c;破译用户意图并提供准确、上下文丰富的响应的方法已变得至关重要。 在本系列文章中&#xff0c;我将深入探讨利用 GAI 重新构想应用程…

Trinamic推出步进电机低压微型电机驱动芯片

前言 TRINAMIC运动控制有限公司宣布推出全球最小的具有专利技术StealthChop™的单芯片电机驱动器。TMC2300为2相步进电机设置了高达1.2A RMS的标准和1.8V…11V DC的电压范围&#xff0c;它只需最低的功耗&#xff0c;让人根本觉察不到有电机的存在。 从现在开始&#xff0c;您只…

springboot139华强北商城二手手机管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

数学知识第七期 高斯消元

前言 高斯大家应该都挺熟悉的吧&#xff0c;伟大的数学家&#xff0c;希望大家能够熟练掌握他的知识&#xff01;&#xff01;&#xff01; 一、高斯消元的基本内容 高斯消元法&#xff08;Gaussian Elimination&#xff09;是一种重要的线性代数算法&#xff0c;用于求解线…

vue3中多个表格怎么同时滚动并且固定表头

说明&#xff1a;这里需分为两种情况来做。第一种亲情况就是没有修改过el-table这个组件的样式&#xff1b;第二种情况就是修改过el-table组件的样式。第一种较为简单就简单略过&#xff0c;这里主要提及第二种做法。 1.需求效果 2.第一种没有修改过el-table这个组件的样式的做…

检测CUDA 是否能访问GPU时回应速度慢【笔记】

SUPWEMICRO 418G-Q20X12 维护记录&#xff1a; 两台设备均已安装CUDA与Pytorch&#xff0c;在检测CUDA 是否能访问GPU&#xff0c;执行torch.cuda.is_available()命令时&#xff0c;一台设备速度秒回应True&#xff0c;但另外一台设备回应速度慢&#xff08;1分钟左右&#xff…

JSON概述以及使用

1&#xff0c;JSON 1.1 概述 概念&#xff1a;JavaScript Object Notation。JavaScript 对象表示法. 如下是 JavaScript 对象的定义格式&#xff1a; {name:"zhangsan",age:23,city:"北京" } 接下来我们再看看 JSON 的格式&#xff1a; {"name&…

linux 使用命令创建mysql账户

目录 前言创建步骤 前言 mysql默认有一个root用户&#xff0c;这个账户权限太大了&#xff0c;用起来不太安全&#xff0c;我们通常是重新那家一个账户用于一般的数据库操作&#xff0c;下面介绍如何通过命令创建一个mysql账户。 创建步骤 登录mysql mysql -u root -p输入roo…

【云上建站】快速在云上构建个人网站3——网站选型和搭建

快速在云上构建个人网站3——网站选型和搭建 一、网站选型二、云市场镜像方式一&#xff1a;方式二&#xff1a;1. 进入ECS实例详情页面&#xff0c;点击停止&#xff0c;确保更换操作系统的之前ECS实例处于已停止状态&#xff0c;点击更换操作系统&#xff0c;进行镜像配置。2…

如何对Ajax请求进行封装操作,解决跨域问题的方法,如何使用core解决跨域

目录 1.Ajax原理 2.为什么要封装 3.如何进行封装 4.如何请求 5.如何解决Ajax跨域问题 6.使用CORS解决Ajax跨域问题 1.服务端 2.客户端 1.Ajax原理 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种通过在后台与服务器进行少量数据交换&…