文章目录
概述
数据流以协程为基础构建,可提供多个值。从概念上来讲,数据流是可通过异步方式进行计算处理的一组数据序列。所发出值的类型必须相同。例如,Flow 是发出整数值的数据流。
在协程中,与仅返回单个值的挂起函数相反,数据流可按顺序发出多个值。
数据流包含三个实体:
- 提供方会生成添加到数据流中的数据。得益于协程,数据流还可以异步生成数据。
- (可选)中介可以修改发送到数据流的值,或修正数据流本身。
- 使用方则使用数据流中的值。
1.使用
1.1 创建数据流
创建数据流有两种常用方式: 第一就是试用数据流构建函数, 第二就是利用扩展方法将原有类型转换成Flow
使用数据构建函数
这里比较常用的函数是 flow()
和 flowOf()
val f = flow {
emit(1)
}
val f2 = flowOf("abc")
val f3 = flowOf("A", "B", "C")
其实 flowof()
是简化版的 flow()
函数,内部帮我们调用了 emit()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JEWWqcWq-1670402003040)(/Users/apple/Downloads/job_files/flow/Xnip2022-11-20_00-25-28.jpg )]
注意:
使用 flow
构建器时,提供方不能提供来自不同 CoroutineContext
的 emit
值。因此,请勿通过创建新协程或使用 withContext
代码块,在不同 CoroutineContext
中调用 emit
可以使用 flowOn
或者 callbackFlow
。
使用扩展方法
扩展方法是 kotlin 标准库中提供的 asFlow()
. 目前基本上覆盖了基本数据类型、lambda、及挂起函数等
下面看一下具体如何使用:
普通lambda 表达式
fun testAsFlow1(blacking: () -> String) {
val flow = blacking.asFlow()
}
挂起函数
suspend fun testAsFlow2(blacking: suspend () -> String) {
val flow = blacking.asFlow()
}
或者以下方式:
suspend fun remoteCall(): String = withContext(Dispatchers.IO) {
return@withContext "ABC"
}
fun remoteCallFlow(): Flow<String> = ::remoteCall.asFlow()
基本数据类型
kotlin 标准库中提供了基本数据类型相关扩展方法,其中 Map
类型不能直接使用asFlow()
需要转换成其支持的类型,再使用 asFlow()
.
fun testAsFlow3() {
// Range 类型
val flow1 = IntRange(1, 100).asFlow()
val flow2 = LongRange(1L, 1000L).asFlow()
// Array 类型
val flow3 = intArrayOf(1, 2, 3).asFlow()
val flow4 = longArrayOf(