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

Flow原理

fun main() {runBlocking {launch {flow4.collect{println("---collect-4")}println("---flow4")}}val flow4 = flow<Boolean>{delay(5000)emit(false)
}

我们分析下整个流程 

1.flow为什么之后在collect之后才会发送数据

2.collect的调用流程

我们先看创建flow的方法

public fun <T> flow(@BuilderInference block: suspend FlowCollector<T>.() -> Unit): Flow<T> = SafeFlow(block)

可以看见是一个方法,返回的是一个SafeFlow对象,然后把我们传入 {
      delay(5000)
       emit(false)
}   
表达式 
的传入到了这个对象中。

private class SafeFlow<T>(private val block: suspend FlowCollector<T>.() -> Unit) : AbstractFlow<T>() {override suspend fun collectSafely(collector: FlowCollector<T>) {collector.block()}
}

然后,这个对象提供一个方法collectSafely,这个时候可以看到,要发送数据,必须得调用SafeFlow的collectSafely方法才行。

接下来我们分析下collect方法。看源码发现需要传入一个FlowCollector接口实现类

public suspend fun collect(collector: FlowCollector<T>)
public fun interface FlowCollector<in T> {//注意这个emit方法public suspend fun emit(value: T)
}

因为我们是使用flow方法返回的SafeFlow对象去调用的,所以我们看下SafeFlow的collect方法。SafeFlow是继承AbstractFlow的类,所以我们看这个类就行

public abstract class AbstractFlow<T> : Flow<T>, CancellableFlow<T> {public final override suspend fun collect(collector: FlowCollector<T>) {//创建SafeCollector对象val safeCollector = SafeCollector(collector, coroutineContext)try {//调用实现类的collectSafely方法,把SafeCollector对象传递过去collectSafely(safeCollector)} finally {safeCollector.releaseIntercepted()}}public abstract suspend fun collectSafely(collector: FlowCollector<T>)
}

再接着查看collectSafely方法,发现调用到了我们传入的闭包

private class SafeFlow<T>(private val block: suspend FlowCollector<T>.() -> Unit) : AbstractFlow<T>() {override suspend fun collectSafely(collector: FlowCollector<T>) {//调用我们传入的闭包,而且他是FlowCollector的扩展函数collector.block()}
}

而我们传入的闭包是suspend FlowCollector<T>.() -> Unit扩展函数,这个对象就是我们collect传入的接口实现类,所以在

val flow4 = flow<Boolean>{
      delay(5000)
       emit(false)
}

方法中调用emit()实际就是调用collect传入接口实现类的emit方法


 

http://www.xdnf.cn/news/186967.html

相关文章:

  • Unity3D引擎框架及用户接口调用方式相关分析及汇总
  • 关系数据的可视化
  • 【数据结构】排序
  • 一、JVM基础概念
  • 全开源、私有化部署!轻量级用户行为分析系统-ClkLog
  • MAC如何安装多版本jdk(以8,11,17为例)
  • 定时器的源码介绍与简单实现——多线程编程简单案例[多线程编程篇(5)]
  • stm32wb55rg (2) 阅读资料手册
  • Leetcode刷题 | Day49_图论01
  • 数字孪生的浪潮:从虚拟镜像到现实世界的 IT 变革
  • 孙宇晨将出席迪拜Token2049 与特朗普次子共话加密未来
  • 【Pandas】pandas DataFrame rmod
  • 基于vue框架的电影推荐系统p0apl(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 60、微服务保姆教程(三)Sentinel---高可用流量管理框架/服务容错组件
  • 微信小程序分页和下拉刷新
  • uniapp 微信小程序遇到的坑
  • 一种改进的YOLOv11网络,用于无人机视角下的小目标检测
  • 深度学习中的正则化简介
  • 如何正确地解读和分析MySQL性能模式和查询分析器提供的性能数据?
  • 【算法应用】基于灰狼算法求解DV-Hop定位问题
  • React Testing Library
  • 2025-4-25 情绪周期视角复盘(mini)
  • 【C语言极简自学笔记】C 语言数组详解:一维数组与二维数组
  • 「OC」源码学习——alloc与init的实现
  • 【博客系统】博客系统第二弹:实现博客列表接口(在 Service 层重新封装 Mapper 层返回结果,避免实体类所有字段都向前端返回)、SimpleDateFormat 类的使用方法
  • 强化学习中关键超参数的详细说明
  • 如何把握邮件发送的黄金时间?
  • TypeScript 入门到进阶全讲解(超全版)
  • DAY8-GDB调试及打桩
  • BOPF Business Object Development