Kotlin 流flow、ShareFlow、StateFlow、Channel的解释与使用

一、介绍

        随着Android接入kotlin开发,Android之前好多模式也渐渐被kotlin替代。开发模式也在做渐进的转型,从MVC到MVP在到MVVP以及现在的MVI等。

        流IO在java中和kotlin中使用率都是比较高的,场景很多。如Java的IO和NIO,再到我们现在使用的RxJava或者升级版的JxJava2。针对JxJava的流处理与转发机制。kotlin语言也自带了flow。

        早MVVM流行的时候,LiveData充当了数据的订阅与流转,但是我们知道,LiveData有一个问题,当Dialog或者当前设置发生旋转,会出现倒灌,这种行为是因为订阅生命发生变化。

针对这些问题,kotlin语言自带了flow流。

二、kotlin flow的介绍

        flow其实与RxJava比较类似,都是基于流在处理订阅的分发。这个flow也被最新的MVI模式所接受,替换了MVVM中的LiveData。

flow又区分冷流和热流。

冷流(Cold Flow)

  •  

    定义与工作原理:冷流是一种异步数据流,它按顺序发出值并正常或异常完成。冷流的特点是,只有当数据被消费者订阅(即调用collect方法后),生产者才开始执行发送数据流的代码。这意味着,如果没有消费者订阅,生产者不会发送任何数据。冷流通常是一对一的关系,即一个生产者对应一个消费者。

  •  

    创建方式:冷流可以通过多种方式创建,包括使用flow{}构建器、flowOfasFlow等方法。这些方法允许开发者根据需要创建冷流,以满足特定的数据生产需求。

  •  

    适用场景:冷流适用于那些不需要持续生产数据,而是在数据被消费时才进行生产的场景。例如,从数据库查询数据、计算结果等,这些操作只有在需要时才会执行。

热流(Hot Flow)

  •  

    定义与工作原理:热流与冷流的主要区别在于,无论是否有消费者订阅,生产者都会持续发送数据。热流支持多个消费者同时订阅,并且生产的数据可以被多个消费者共享。热流通过stateInshareIn操作符实现,可以将任何流转化为热流。

  •  

    适用场景:热流适用于需要持续提供数据给多个消费者的场景,如实时数据更新、传感器数据读取等。由于热流能够同时支持多个消费者,因此在需要共享数据给多个组件或界面时非常有用。

通过冷热流区分我们可以知道冷流和热流可以相互转换。冷流是一对一服务,热流是一对多服务。

这个也就导致,在后期的开发过程中,订阅和消费,流的互相转换。

1对多

1对1

 三、流的使用

        接下来主要介绍Flow、SateFlow、ShareFlow以及Channel的用法,冷流和热流互换。这些流基本都是用到了协程,所以不能直接使用。

3.1.Flow

flow:这个老六就是热流,只要你订阅就一直发,不停的发,只要emit中的都有记录,而且内部还维持了一个index,可以知道目前下发了多少次。热流不管是什么视乎订阅,都会有。

场景:热流是无线转发,一般使用在状态订阅转发,比如平台关闭了id,可以直接放进去,后面其他模块如果可以订阅,查找当前状态。包括配合webscoket可以做很多事情。

   var count=0val myflow= flow<String> {repeat(3,{count++emit("当前是=${count}")})}/*** flow是一直保持的,只要订阅一次,就会发送一次,而且上次的记录一直保持。collect需要通过协程来处理* */lifecycleScope.launch {myflow.flowOn(Dispatchers.Main).collect({textview.append("collect="+it+"\n")})myflow.collectIndexed { index, value ->textview.append("collectIndexed="+value+",${index}\n")}myflow.flatMapConcat { it->flow {emit("map=${it}")}}.collect({textview.append("${it}\n")})myflow.flatMapMerge {flow { emit("flatMapMerge=${it}")emit("MapMerge=最近")}}.collect({textview.append("${it}\n")})myflow.flatMapLatest {flow { emit("flatMapLatest=${it}")emit("flatMapLatest=最近")}}.collect({textview.append("${it}\n")})//热流转冷val reciver=myflow.produceIn(this).receiveCatching()textview.append("produceIn=${reciver.getOrNull()}\n")}

3.2 SateFlow

        状态流属于冷流,订阅会收到最近一次,如果订阅没有设置value,接受的是默认值,如果当前值没有变化,也不会发送,也就是当前值和上次会进行比较,如果一样不会继续订阅。是一对一,多次订阅,第一个collect完,后面将不会再收到订阅事件。

        val sateFlow=MutableStateFlow("")var num=0findViewById<View>(R.id.btn_click_state)?.setOnClickListener {lifecycleScope.launch {//默认连接的时候会收到最近一次的,如果最近都没有设置value或者emit,那么收到的是默认值sateFlow.value="ssssss"sateFlow.value="ssssss111111111111=${num++}"}}lifecycleScope.launch {sateFlow.collectIndexed { index, value ->textview.append("index=${index},value=${value}\n")}sateFlow.collect({textview.append("${it}\n")})sateFlow.emit("aaaa")}

3.3 ShareFlow

        shareflow和其他的flow不一样,在构造的时候有三个参数,第一个是replay重复多少次,和缓存次数,后面是缓存流类型,内部也是可以多次订阅,但是collectIndexed和collect类型只能出现一个。但是一个类型可以多次订阅

public fun <T> MutableSharedFlow(replay: Int = 0,extraBufferCapacity: Int = 0,onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
)

默认都为0,所以不会重复多次发送,这个就很好规避倒灌的问题。不会因为生命周期发生变化,内部出现多次订阅和消费的情况。

share流也是要在协程里的,emit协程体中,在emit之前不能进行订阅(collect),否则会出现阻塞,导致事件无法往下走,后面的emit无法发出,可以在多个协程体中进行订阅。

lifecycleScope.launch {//多次订阅也不会发送,只会优先发给第一个订阅的人shareFloow.collect {  value ->textview.append("1collect="+value+"\n")}shareFloow.collect {  value ->textview.append("2collect="+value+"\n")}shareFloow.collectIndexed { index, value ->textview.append("collectIndexed="+value+",${index}\n")}}findViewById<View>(R.id.btn_click_share)?.setOnClickListener {var count=0/*** flow是一直保持的,只要订阅一次,就会发送一次,而且上次的记录一直保持。collect需要通过协程来处理* */lifecycleScope.launch {shareFloow.emit("我在测试ShareFlow1")shareFloow.emit("我在测试ShareFlow2")shareFloow.collect {  value ->textview.append("in--1--collect="+value+"\n")}shareFloow.collect {  value ->textview.append("in--2--collect="+value+"\n")}}}

3.4Channel

        channel其实在很多地方都有,管道。Java中也有。这里也是可以通过管道channel来进行转发和订阅的。这个用法可以将管道转成flow,进行各种订阅

       //后订阅这,不再接受到之前的事件val channel= Channel<String>()var count=0findViewById<View>(R.id.btn_click_channel).setOnClickListener {lifecycleScope.launch{channel.send( "count=1")channel.send( "count=2")}}lifecycleScope.launch {//类似shareflow一直订阅,一直
//            channel.consumeEach {
//                textview.append("consumeEach=${it}\n")
//            }//只能订阅一次,且接受是第一次,后面不再接受
//            channel.consume {
//                textview.append("consume=${this.receive()}\n")
//            }//只消费一次,无法再继续接受,只接受第一次发送的事件
//            channel.consumeAsFlow().produceIn(this).consume{
//                textview.append("consumeAsFlow22=${receive()}\n")
//            }//会一直接受,和shareflow类似channel.consumeAsFlow().collect{textview.append("consumeAsFlow11=${it}\n")}}

他的订阅类型很多

1.consumeEach:一直订阅,只要发送就会接受

2.consume:单次消费,订阅后,只接受第一次,后面再发送也不会接受

3.channel.consumeAsFlow():转成热流

4.channel.consumeAsFlow().collect:热流的用法

四、总结

通过上面的分析,不管冷流还是热流以及管道,都有自己的特性。

冷热流以及管道可以互相转换

也可以转成LiveData

所以,大家在用的时候要注意,如果需要注意倒灌可以优先考虑ShareFlow,需要长期订阅用flow

注意:

但是sateFlow会出现倒灌情况,和LiveData一样,如何规避?其实可以用ShareFlow替代

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

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

相关文章

Java、python、php版的高校失物招领平台(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

kali网络代理设置

首先主机必须有自己的代理。记住主机的ip和代理端口。 在kali中打开终端&#xff1a; vim /etc/proxychains4.conf输入代理进行更改 把这行注释掉&#xff0c;在下一行输入 socks5 主机ip 代理端口 点击esc&#xff0c;在:wq退出保存。 配置完成。

Salesforce 发布开源大模型 xGen-MM

xGen-MM 论文 在当今 AI 技术飞速发展的时代&#xff0c;一个新的多模态 AI 模型悄然崛起&#xff0c;引起了业界的广泛关注。这个由 Salesforce 推出的开源模型—— xGen-MM&#xff0c;正以其惊人的全能特性和独特优势&#xff0c;在 AI 领域掀起一阵旋风。那么&#xff0c;x…

Why Does ChatGPT Fall Short in Providing Truthful Answers?

文章目录 题目摘要简介相关工作模型和数据集结果事实性背后的能力提高 QA 的事实性结论 题目 为什么 ChatGPT 无法提供真实的答案&#xff1f; 论文地址:https://arxiv.org/abs/2304.10513 摘要 ChatGPT 等大型语言模型的最新进展已显示出影响人类生活各个方面的巨大潜力。然而…

数据库学习(进阶)

数据库学习&#xff08;进阶&#xff09; Mysql结构:连接层&#xff1a;服务层&#xff08;核心层&#xff09;&#xff1a;存储引擎层&#xff1a;系统文件层&#xff1a; 存储引擎&#xff08;概述&#xff09;:存储引擎特点&#xff1a;InnoDB存储引擎&#xff1a;(为并发条…

【C++ 面试 - 面向对象】每日 3 题(二)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

C语言钥匙迷宫2.0

目录 开头程序程序的流程图程序游玩的效果结尾 开头 大家好&#xff0c;我叫这是我58。废话不多说&#xff0c;咱们直接开始。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <Windows.h> enum color {Y,B,R …

裸金属服务器和裸金属云服务器:区别、优势与选择

首先&#xff0c;必须肯定的是&#xff1a;裸金属服务器和裸金属云服务器是有区别的。 ‌ 二者的概述 裸金属服务器&#xff08;‌Bare Metal Server&#xff09;‌是一种物理服务器&#xff0c;‌它直接在硬件上运行&#xff0c;‌没有额外的虚拟化层。‌这意味着每个应用程…

ChatGLM-4-9b-chat本地化|天翼云GPU上vLLM本地部署开源模型完整攻略

“ 拥有一个私有化的领先国产开源大模型&#xff1f;本文详细介绍了如何在天翼云GPU上使用vLLM部署ChatGLM-4-9b-chat本地化模型的完整攻略&#xff0c;助您快速上手。” 01 — vLLM 本来打算用ollama在GPU服务器上部署开源模型GLM4&#xff0c;在之前文章有部署教程&#xff1…

刷题篇 - 03

题目一&#xff1a; 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; public ListNode removeElements(ListNode head, int val) {//1. 如果链表为null&#xff0c;直接返回headif (head null) {return head;}//2. 定义快慢指针ListNode pre head;ListNode del …

Tomcat:Web 领域的闪耀明珠,魅力何在?

一、Web技术 HTTP 协议&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最为广泛的一种网络协议。它的主要作用是在客户端和服务器之间传输超文本数据&#xff0c;如网页、图片、视频等。 HTTP 协议的特点 无状态性 HTTP 协议是…

STM32H7双路CAN踩坑记录

STM32H7双路CAN踩坑记录 目录 STM32H7双路CAN踩坑记录1 问题描述2 原因分析3 解决办法4 CAN配置参考代码 1 问题描述 STM32的CAN1和CAN2无法同时使用。 注&#xff1a;MCU使用的是STM32H743&#xff0c;其他型号不确定是否一样&#xff0c;本文只以STM32H743举例说明。 2 原因…

了解同步带选择同步带

同步带和轮选型 同步带传动属于皮带传动&#xff0c;但是改进了传统皮带传动无法保持严格的传动比的打滑问题&#xff0c;传统皮带传动依靠皮带和皮带轮张紧时产生的摩擦力传输动力&#xff0c;但是从动轮遇到障碍或超载荷时&#xff0c;皮带会在皮带轮产生滑动。 解决打滑问题…

项目1 物流仓库管理系统

一、项目概述 本项目旨在开发一个功能全面的物流仓库管理系统&#xff0c;以数字化手段优化仓库作业流程&#xff0c;提高管理效率。系统集成了前端用户交互界面与后端数据处理逻辑&#xff0c;涵盖了从用户注册登录、订单管理、货单跟踪到用户信息维护等多个核心业务模块。通…

前端3d动画-----平移 transform: translate3d()

必须加这个属性&#xff1a;transform-style: preserve-3d; perspective: 900px; 设置了景深才能感到近大远小的感觉 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&q…

分享一个基于python爬虫的“今日头条”新闻数据分析可视化系统(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

AI赋能软件测试:从自动化到智能化,让测试工作事半功倍

引言 在当今这个日新月异的数字时代&#xff0c;人工智能&#xff08;AI&#xff09;正以不可阻挡之势渗透并重塑着各行各业&#xff0c;其中&#xff0c;软件开发与测试领域更是迎来了前所未有的变革。随着软件系统的复杂性日益增加&#xff0c;用户对软件质量、性能及安全性的…

Nginx笔记(高级)

扩容 通过扩容提升整体吞吐量 单机垂直扩容&#xff1a;硬件资源增加 云服务资源增加 整机&#xff1a;IBM、浪潮、DELL、HP等CPU/主板&#xff1a;更新到主流网卡&#xff1a;10G/40G网卡磁盘&#xff1a;SAS(SCSI) HDD&#xff08;机械&#xff09;、HHD&#xff08;混合&…

android13布局查看工具 无源码查看布局 在线查找ui布局id

总纲 android13 rom 开发总纲说明 目录 1.前言 2.工具介绍 2.1工具1 2.2工具2 2.3工具3 2.4工具4 3.彩蛋 1.前言 Android 13提供了一些工具来帮助开发人员查看和优化应用的布局。方便的让我们找到具体应用的布局文件等信息。 2.工具介绍 2.1工具1 老版本DDMS&#x…