前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【Kotlin 协程】Flow 异步流 ③ ( 冷流 | 流被收集时运行 | 流的连续性 )

【Kotlin 协程】Flow 异步流 ③ ( 冷流 | 流被收集时运行 | 流的连续性 )

作者头像
韩曙亮
发布于 2023-03-30 10:29:09
发布于 2023-03-30 10:29:09
55300
代码可运行
举报
运行总次数:0
代码可运行

文章目录

一、冷流 ( 流被收集时运行 )


Flow 异步流 的 构建器函数 flow 函数 中的 代码 ,

在 调用 Flow#collect 函数 时 , 也就是在 Flow 异步流 收集元素时 ,

才会 执行 flow 构建器 中的代码 ;

这种机制的异步流 称为 冷流 ;

代码示例 : 在 flow 构建器的开始位置 , 发射元素 , 在主线程中 Flow#collect 收集元素位置 , 添加日志信息 , 查看日志打印的时机 ;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.AbstractFlow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 携程中调用挂起函数返回一个 Flow 异步流
        runBlocking {
            println("Flow 异步流 开始收集元素")
            // 调用 Flow#collect 函数, 可以获取在异步流中产生的元素
            flowFunction().collect {
                // 每隔 500ms 即可拿到一个 Int 元素
                // 并且该操作是异步操作, 不会阻塞调用线程
                println("收集到元素 $it")
                println(it)
            }
        }
    }

    /**
     * 使用 flow 构建器 Flow 异步流
     * 在该异步流中, 异步地产生 Int 元素
     */
    suspend fun flowFunction() = flow<Int> {
        println("Flow 异步流开始执行")
        for (i in 0..2) {
            // 挂起函数 挂起 500ms
            // 在协程中, 该挂起操作不会阻塞调用线程, 会继续执行其它代码指令
            // 500ms 恢复执行, 继续执行挂起函数之后的后续代码指令
            delay(500)
            // 每隔 500ms 产生一个元素
            // 通过调用 FlowCollector#emit 生成一个元素
            println("发射元素 $i")
            emit(i)
        }
    }
}

执行结果 : 根据打印的日志可知 , 异步流收集元素后 , 才开始执行 flow 构建器 中的代码 ;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2022-12-22 16:57:31.969 26807-26807/kim.hsl.coroutine I/System.out: Flow 异步流 开始收集元素
2022-12-22 16:57:31.978 26807-26807/kim.hsl.coroutine I/System.out: Flow 异步流开始执行
2022-12-22 16:57:32.512 26807-26807/kim.hsl.coroutine I/System.out: 发射元素 0
2022-12-22 16:57:32.523 26807-26807/kim.hsl.coroutine I/System.out: 收集到元素 0
2022-12-22 16:57:32.524 26807-26807/kim.hsl.coroutine I/System.out: 0
2022-12-22 16:57:33.066 26807-26807/kim.hsl.coroutine I/System.out: 发射元素 1
2022-12-22 16:57:33.066 26807-26807/kim.hsl.coroutine I/System.out: 收集到元素 1
2022-12-22 16:57:33.066 26807-26807/kim.hsl.coroutine I/System.out: 1
2022-12-22 16:57:33.574 26807-26807/kim.hsl.coroutine I/System.out: 发射元素 2
2022-12-22 16:57:33.574 26807-26807/kim.hsl.coroutine I/System.out: 收集到元素 2
2022-12-22 16:57:33.574 26807-26807/kim.hsl.coroutine I/System.out: 2

二、流的连续性


Flow 流 的 每次调用 Flow#collect 收集元素的操作 , 都是 按照 固定顺序 执行的 , 使用 特殊操作符 可以改变该顺序 ;

Flow 异步流 中的元素 , 按照顺序进行 FlowCollector#emit 发射操作 , 则 调用 Flow#collect 收集元素时获取的元素 也是按照顺序获取的 ;

在流的 上游 到 下游 发射元素的过程中 , 会 使用 过渡操作符 处理每个 FlowCollector#emit 发射出的元素 , 最终才交给 最末端的 操作符 ;

代码示例 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package kim.hsl.coroutine

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 携程中调用挂起函数返回一个 Flow 异步流
        runBlocking {
            // 使用下面的方式可以快速构建一个 Flow 流
            (0..5).asFlow().filter {
                // 奇数才能继续向下流
                // 偶数被过滤掉了
                it % 2 == 1
            }.map {
                // 遍历元素, 将其拼接成字符串
                "学号 : $it"
            }.collect {
                // 打印收集的元素
                println(it)
            }
        }
    }
}

执行结果 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2022-12-22 17:51:46.301 5299-5299/kim.hsl.coroutine I/System.out: 学号 : 1
2022-12-22 17:51:46.301 5299-5299/kim.hsl.coroutine I/System.out: 学号 : 3
2022-12-22 17:51:46.301 5299-5299/kim.hsl.coroutine I/System.out: 学号 : 5
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Kotlin 协程】协程并发安全问题 ( 使用 Atomic 并发安全类型 | 使用 Channel 通道 | 使用 Mutext 轻量级锁 | 使用 Semaphore 轻量级信号量 )
协程不安全数据访问代码示例 : 同时开启 100000 个协程 , 对相同的 int 值进行累加 , 等所有协程访问完毕 , 查看最终结果 , 发现最终累加不足 100000 ;
韩曙亮
2023/03/30
6820
【Kotlin 协程】协程并发安全问题 ( 使用 Atomic 并发安全类型 | 使用 Channel 通道 | 使用 Mutext 轻量级锁 | 使用 Semaphore 轻量级信号量 )
【Kotlin 协程】协程中的多路复用技术 ② ( select 函数原型 | SelectClauseN 事件 | 查看挂起函数是否支持 select )
在上一篇博客 【Kotlin 协程】协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 ) 中 , 介绍了 协程多路复用技术 , 多路复用 主要使用 select 代码块 实现 ,
韩曙亮
2023/03/30
1.2K0
【Kotlin 协程】协程中的多路复用技术 ② ( select 函数原型 | SelectClauseN 事件 | 查看挂起函数是否支持 select )
【Kotlin 协程】Flow 异步流 ④ ( 流的构建器函数 | flow 构建器函数 | flowOf 构建器函数 | asFlow 构建器函数 )
在 flow 流构建器中 , 调用 FlowCollector#emit 函数 发射元素 , 然后在外部 调用 Flow#collect 函数 收集元素 ;
韩曙亮
2023/03/30
5080
【Kotlin 协程】Flow 异步流 ④ ( 流的构建器函数 | flow 构建器函数 | flowOf 构建器函数 | asFlow 构建器函数 )
【Kotlin 协程】Flow 异步流 ⑤ ( 流的上下文 | 上下文保存 | 查看流发射和收集的协程 | 不能在不同协程中执行流的发射和收集操作 | 修改流发射的协程上下文 | flowOn函数 )
Flow 异步流 收集元素 的操作 , 一般是在 协程上下文 中进行的 , 如 : 在协程中调用 Flow#collect 函数 , 收集元素 ;
韩曙亮
2023/03/30
9520
【Kotlin 协程】Flow 异步流 ⑤ ( 流的上下文 | 上下文保存 | 查看流发射和收集的协程 | 不能在不同协程中执行流的发射和收集操作 | 修改流发射的协程上下文 | flowOn函数 )
【Kotlin 协程】Flow 操作符 ① ( 过渡操作符 | map 操作符 | transform 操作符 | 限长操作符 | take 操作符 )
代码示例 : 将 Flow 中发射的 Int 元素 转为 字符串 ; 通过 map 操作符 , 将 Int 类型的元素 转为 字符串类型 元素 ;
韩曙亮
2023/03/30
8560
【Kotlin 协程】Flow 操作符 ① ( 过渡操作符 | map 操作符 | transform 操作符 | 限长操作符 | take 操作符 )
【Kotlin 协程】Flow 异步流 ⑦ ( 调用 FlowCollector#emit 发射元素时自动执行 Flow 流的取消检测 | 启用检测 Flow 流的取消cancellable函数 )
在 Flow 流构建器 中 , 每次 调用 FlowCollector#emit 发射元素时 ,
韩曙亮
2023/03/30
9570
【Kotlin 协程】Flow 异步流 ⑦ ( 调用 FlowCollector#emit 发射元素时自动执行 Flow 流的取消检测 | 启用检测 Flow 流的取消cancellable函数 )
【Kotlin 协程】Flow 流展平 ( 连接模式 flatMapConcat | 合并模式 flatMapMerge | 最新展平模式 flatMapLatest )
Flow 流在 接收元素 时 , 可能需要 另一个 流的元素 , 两个流之间进行 交互的操作 就是 展平 , 常见的 展平模式有 :
韩曙亮
2023/03/30
1.3K0
【Kotlin 协程】Flow 流展平 ( 连接模式 flatMapConcat | 合并模式 flatMapMerge | 最新展平模式 flatMapLatest )
【Kotlin 协程】Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )
在上一篇博客 【Kotlin 协程】Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 ) 中 分析了 以异步方式 分别使用 序列 和 集合 返回多个返回值 ,
韩曙亮
2023/03/30
1.6K0
【Kotlin 协程】Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )
【Kotlin 协程】Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )
异常代码示例 : 如果收集的元素 it <= 1 , 则检查通过 , 否则当 it > 1 时 会报异常 ;
韩曙亮
2023/03/30
1.9K0
【Kotlin 协程】Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )
【Kotlin 协程】Flow 流组合 ( Flow#zip 组合多个流 | 新组合流的元素收集间隔与被组合流元素发射间隔的联系 )
假如两个 Flow 流的 元素发射 不同步 , 则 先发射的元素 , 需要等待对应顺序的 后发射的元素到来 ;
韩曙亮
2023/03/30
1.1K0
【Kotlin 协程】Flow 流组合 ( Flow#zip 组合多个流 | 新组合流的元素收集间隔与被组合流元素发射间隔的联系 )
【Kotlin 协程】Flow 操作符 ② ( 末端操作符 | collect 操作符 | reduce 操作符 | single 操作符 | first 操作符 | toList 操作符 )
末端操作符 指的是 在 Flow 流最末端 调用 挂起函数 收集元素 的操作符 , 最常见的 末端操作符 就是 collect 操作符 ;
韩曙亮
2023/03/30
1K0
【Kotlin 协程】Flow 操作符 ② ( 末端操作符 | collect 操作符 | reduce 操作符 | single 操作符 | first 操作符 | toList 操作符 )
【Kotlin 协程】Channel 通道 ① ( Channel#send 发送数据 | Channel#receive 接收数据 )
协程中的 Channel 通道 是 并发的安全队列 , 不同的协程之间 可以 借助 Channel 通道 进行通信 ;
韩曙亮
2023/03/30
8740
【Kotlin 协程】Channel 通道 ① ( Channel#send 发送数据 | Channel#receive 接收数据 )
【Kotlin 协程】Flow 异步流 ⑥ ( 调用 Flow#launchIn 函数指定流收集协程 | 通过取消流收集所在的协程取消流 )
响应式编程 , 是 基于事件驱动 的 , 在 Flow 流中会产生源源不断的事件 , 就是 发射元素操作 ;
韩曙亮
2023/03/30
8720
【Kotlin 协程】Flow 异步流 ⑥ ( 调用 Flow#launchIn 函数指定流收集协程 | 通过取消流收集所在的协程取消流 )
【Kotlin 协程】协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 )
在 协程 中 , 可以通过 复用 多个 await 的方式 , 实现 多路复用 ;
韩曙亮
2023/03/30
8280
【Kotlin 协程】协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 )
【Kotlin 协程】Flow 异步流 ⑧ ( 背压概念 | 使用缓冲处理背压问题 | 使用 flowOn 处理背压问题 | 从提高收集元素效率方向解决背压问题 )
数据 生产者 的 生产效率 大于 数据 消费者 的 消费效率 , 就会产生 背压 ;
韩曙亮
2023/03/30
6660
【Kotlin 协程】Flow 异步流 ⑧ ( 背压概念 | 使用缓冲处理背压问题 | 使用 flowOn 处理背压问题 | 从提高收集元素效率方向解决背压问题 )
【Kotlin 协程】Channel 通道 ③ ( CoroutineScope#produce 构造生产者协程 | CoroutineScope#actor 构造消费者协程 )
通过 CoroutineScope#produce 函数 , 可以快速构造一个 生产者协程 , 其返回值是 ReceiveChannel 实例对象 , 这样就可以在消费者协程中通过该 ReceiveChannel 实例获取并消费数据 ;
韩曙亮
2023/03/30
5190
【Kotlin 协程】Channel 通道 ③ ( CoroutineScope#produce 构造生产者协程 | CoroutineScope#actor 构造消费者协程 )
【Kotlin 协程】Channel 通道 ② ( Channel 通道容量 | Channel 通道迭代 | 使用 iterator 迭代器进行迭代 | 使用 for in 循环进行迭代 )
直到 调用 Channel#receive 函数 取走了缓冲区中的数据 , 缓冲区 有了空间 , Channel#send 函数才会恢复执行 ;
韩曙亮
2023/03/30
7610
【Kotlin 协程】Channel 通道 ② ( Channel 通道容量 | Channel 通道迭代 | 使用 iterator 迭代器进行迭代 | 使用 for in 循环进行迭代 )
Kotlin协程与并发编程
🍆在学习之前,推荐大家看一篇kotlin基础教程,深入学习 Kotlin:基础语法与高级特性
Marblog
2024/11/14
1470
kotlin--Flow的运用
1.可以使用flow构建函数构建一个Flow类型返回值的函数 2.flow{}构建体中可以调用挂起函数,即上流 3.上流使用emit函数发射值 4.下流使用collect函数收集值
aruba
2021/12/06
6790
kotlin--Flow的运用
Kotlin中的冷流和热流以及如何让Flow停下来
在Kotlin中,Flow是Kotlin Coroutines库中的一个重要概念,用于处理异步和并发数据流。Flow可以帮助你轻松管理和处理异步的、实时的数据流,比如从网络获取的数据流、数据库更新流等等。
AntDream
2024/09/13
2540
Kotlin中的冷流和热流以及如何让Flow停下来
推荐阅读
【Kotlin 协程】协程并发安全问题 ( 使用 Atomic 并发安全类型 | 使用 Channel 通道 | 使用 Mutext 轻量级锁 | 使用 Semaphore 轻量级信号量 )
6820
【Kotlin 协程】协程中的多路复用技术 ② ( select 函数原型 | SelectClauseN 事件 | 查看挂起函数是否支持 select )
1.2K0
【Kotlin 协程】Flow 异步流 ④ ( 流的构建器函数 | flow 构建器函数 | flowOf 构建器函数 | asFlow 构建器函数 )
5080
【Kotlin 协程】Flow 异步流 ⑤ ( 流的上下文 | 上下文保存 | 查看流发射和收集的协程 | 不能在不同协程中执行流的发射和收集操作 | 修改流发射的协程上下文 | flowOn函数 )
9520
【Kotlin 协程】Flow 操作符 ① ( 过渡操作符 | map 操作符 | transform 操作符 | 限长操作符 | take 操作符 )
8560
【Kotlin 协程】Flow 异步流 ⑦ ( 调用 FlowCollector#emit 发射元素时自动执行 Flow 流的取消检测 | 启用检测 Flow 流的取消cancellable函数 )
9570
【Kotlin 协程】Flow 流展平 ( 连接模式 flatMapConcat | 合并模式 flatMapMerge | 最新展平模式 flatMapLatest )
1.3K0
【Kotlin 协程】Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )
1.6K0
【Kotlin 协程】Flow 流异常处理 ( 收集元素异常处理 | 使用 try...catch 代码块捕获处理异常 | 发射元素时异常处理 | 使用 Flow#catch 函数捕获处理异常 )
1.9K0
【Kotlin 协程】Flow 流组合 ( Flow#zip 组合多个流 | 新组合流的元素收集间隔与被组合流元素发射间隔的联系 )
1.1K0
【Kotlin 协程】Flow 操作符 ② ( 末端操作符 | collect 操作符 | reduce 操作符 | single 操作符 | first 操作符 | toList 操作符 )
1K0
【Kotlin 协程】Channel 通道 ① ( Channel#send 发送数据 | Channel#receive 接收数据 )
8740
【Kotlin 协程】Flow 异步流 ⑥ ( 调用 Flow#launchIn 函数指定流收集协程 | 通过取消流收集所在的协程取消流 )
8720
【Kotlin 协程】协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 )
8280
【Kotlin 协程】Flow 异步流 ⑧ ( 背压概念 | 使用缓冲处理背压问题 | 使用 flowOn 处理背压问题 | 从提高收集元素效率方向解决背压问题 )
6660
【Kotlin 协程】Channel 通道 ③ ( CoroutineScope#produce 构造生产者协程 | CoroutineScope#actor 构造消费者协程 )
5190
【Kotlin 协程】Channel 通道 ② ( Channel 通道容量 | Channel 通道迭代 | 使用 iterator 迭代器进行迭代 | 使用 for in 循环进行迭代 )
7610
Kotlin协程与并发编程
1470
kotlin--Flow的运用
6790
Kotlin中的冷流和热流以及如何让Flow停下来
2540
相关推荐
【Kotlin 协程】协程并发安全问题 ( 使用 Atomic 并发安全类型 | 使用 Channel 通道 | 使用 Mutext 轻量级锁 | 使用 Semaphore 轻量级信号量 )
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文