ITmob-Ly
发布于 2024-04-17 / 190 阅读
0

kotlin 协程中 Collect 与 CollectLatest 的区别和选择

Kotlin-Blog

collectcollectLatest 都是 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
    }
}

collectcollectLatest 的选择

根据是否需需要处理所有数据进行选择:

  • collect 在需要处理数据流中的所有数据时使用。
  • collectLatest 在当只关心最新状态,只需要处理最新值并且不希望处理过时的数据时使用。