flow 介绍
之前介绍的启动协程方法,比如 launch、async 都是协程的单次启动。如果有复杂场景,比如发送多个数据,就需要使用 flow 数据流。在 flow 中,数据如水流一样经过上游发送,中间站处理,下游接收。
创建 flow
创建 flow 有 3 种方式:
- flow{}
- flowOf()
- asFlow()
flow
flow{} 中使用 emit 发送数据。
fun flowEmit() = runBlocking {
flow {
emit(1)
emit(2)
emit(3)
emit(4)
emit(5)
}
.filter {
it > 2
}
.map {
it * 2
}
.take(2)
.collect {
// 6 8
println(it)
}
}
flowOf
flowOf() 可以将指定的一串数据转换为 flow,接收可变参数。
fun flowOfFun() = runBlocking {
flowOf(1, 2, 3, 4, 5)
.filter {
it > 2 }
.map {
it * 2 }
.take(2)
.collect {
// 6 8
println(it)
}
listOf(1, 2, 3, 4, 5)
.filter {
it > 2 }
.map {
it * 2 }
.take(2)
.forEach {
// 6 8
println(it)
}
}
asFlow
asFlow() 可以将 List 集合转换为 flow。toList() 可以将 flow 转换为 List 集合。
fun flow2list() = runBlocking {
flowOf(1, 2, 3, 4, 5)
// flow to list
.toList()
.filter {
it > 2 }
.map {
it * 2 }
.take(2)
.forEach {
println(it)
}
listOf(1, 2, 3, 4, 5)
// list as flow
.asFlow()
.filter {
it > 2 }
.map {
it * 2 }
.take(2)
.collect {
println(it)
}
}
中间操作符
创建 flow 之后使用中间操作符处理 flow 的每一个数据。flow 的中间操作符和 list 集合的操作符非常类似。
常用中间操作符:
- filter
- map
- take
filter
filter 传入判断条件,条件满足时过滤数据,否则不将数据流向下游。
map
map 传入映射函数,将每个数据传入映射函数,得到结果继续传入下游。
take
take 传入非负整数 n,取前 n 个数据传入下游。
fun flowEmit() = runBlocking {
flow {
emit(1)
emit(2)
emit(3)
emit(4)
emit(5)
}
.filter {
it > 2
}
.map {
it * 2
}
.take(2)
.collect {
// 6 8
println(it)
}
}
终止操作符
collect 是 flow 的终止操作符,收集每一个数据经过中间操作符后的最终结果,表示 flow 流的终止,后面不能再调用中间操作符。
除了 collect,还有一些其他的终止操作符,first、single、fold、reduce。
collect
返回所有元素,结束 flow。
fun flowEmit() = runBlocking {
flow {
emit(1)
emit(2)
emit(3)
emit(4)
emit(5)
}
.filter {
it > 2
}
.map {
it * 2
}
.take(2)
.collect {
// 6 8
println(it)
}
}
first
返回第一个元素,结束 flow。
fun flowFirst() = runBlocking {
val first = flow {
emit(1)
emit(2)
emit(3)
emit