collect
和 collectLatest
都是 Kotlin 协程中收集给定 Flow/数据流 的终端运算符,用于处理数据流中发出的值。但是它们有不同的用途,因此使用时需要根据它们的区别正确选择。
collect 对上游数据流流发出的每个值都收集并完整执行 lambda 函数的操作,而 collectLatest 如果在前一个值收集并执行 lambda 完成之前发出新值,则取消任何正在进行的收集和 lambda 函数。
collect
用途:收集处理数据流发出的所有数据
即使多个收集器都连接到同一个数据流时,每个收集器也都将接收和处理所有发出的数据。所以当需要处理所有数据时,collect
是最好的选择。
package cn.itmob.sample
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
flow {
emit(1)
delay(50)
emit(2)
}.collect { value ->
println("Collecting $value")
delay(100) // 模拟耗时操作(发送的所有值都将被处理)
println("$value collected")
}
// 输出:Collecting 1, 1 collected, Collecting 2, 2 collected
}
}
collect
有可能会阻塞当前协程,因此在使用时需要考虑数据流处理的性能
collectLatest
用途:仅处理数据流发出的最新数据
如果在收集器正在处理先前的数据时有新值发出,收集器将取消正在收集和处理先前数据的 lambda 操作并重新开始处理新值,因此当只关心最新数据(如:更新 UI 或管理最新状态)时,collectLatest
是最好的选择。
package cn.itmob.sample
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
flow {
emit(1)
delay(50)
emit(2)
}.collectLatest { value ->
println("Collecting $value")
delay(100) // 模拟耗时操作(前值的操作还未完成时有新值发出,前值的操作将取消)
println("$value collected")
}
// 输出:Collecting 1, Collecting 2, 2 collected
}
}
collect
和 collectLatest
的选择
根据是否需需要处理所有数据进行选择:
collect
在需要处理数据流中的所有数据时使用。
collectLatest
在当只关心最新状态,只需要处理最新值并且不希望处理过时的数据时使用。