Kotlin协程中的Flow主要用于处理复杂的异步数据,以一种”流“的方式,从上到下依次处理,和RxJava的处理方式类型,但是比后者更加强大。
Flow基本概念
Flow中基本上有三个概念,即 发送方,处理中间层,接收方,可以类比水利发电站中的上游,发电站,下游的概念, 数据从上游开始发送”流淌“至中间站被”处理“了一下,又流淌到了下游。
flow { // 发送方、上游emit(1)// 挂起函数,发送数据emit(2)emit(3)emit(4)emit(5)
}
.filter { it > 2 }// 中转站,处理数据
.map { it * 2 }
.take(2)
.collect{ // 接收方,下游println(it)
}
输出内容:
6
8
通过上面代码我们可以看到,基于一种链式调用api的方式,流式的进行处理数据还是很棒的,接下来具体看一下上面的组成:
- flow{},是个高阶函数,主要用于创建一个新的Flow。在其Lambda函数内部使用了emit()挂起函数进行发送数据。
- filter{}、map{}、take{},属于中间处理层,也是中间数据处理的操作符,Flow最大的优势,就是它的操作符跟集合操作符高度一致。只要会用List、Sequence,那么就可以快速上手 Flow 的操作符。
- collect{},下游接收方,也成为终止操作符,它的作用其实只有一个:终止Flow数据流,并且接收这些数据。
其他创建Flow的方式还是flowOf()函数,示例代码如下
fun main() = runBlocking{aassssssssaaaaaaaasflowOf(1,2,3,4,5).filter { it > 2 }.map { it * 2 }.take(2).collect{println("flowof: $it")}
}
我们在看一下list集合的操作示例
listOf(1,2,3,4,5).filter { it > 2 }.map { it * 2 }.take(2).forEach{println("listof: $it")}
通过以上对比发现,两者的基本操作几乎一致,Kotlin也提供了两者相互转换的API,Flow.toList()、List.asFlow()这两个扩展函数,让数据在 List、Flow 之间来回转换,示例代码如下:
//flow 转listflowOf(1,2,3).toList().filter { it > 1 }.map { it * 2 }.take(2).forEach{println(it)}// list 转 flowlistOf(1,2,3).asFlow().filter { it > 2 }.map { it * 2 }.take(2).collect{println(it)}
Flow生命周期
虽然从上面操作看和集合类型,但是Flow还是有些特殊操作符的,毕竟它是协程的一部分,和Channel不同,Flow是有生命周期的,只是以操作符的形式回调而已,比如on