KotlinFlow的Collect是否只是内部的kotlinx.coroutines API?

f4t66c6m  于 2023-05-18  发布在  Kotlin
关注(0)|答案(7)|浏览(349)

以www.example.com为例https://kotlinlang.org/docs/reference/coroutines/flow.html#flows-are-cold

fun simple(): Flow<Int> = flow { 
    println("Flow started")
    for (i in 1..3) {
        delay(100)
        emit(i)
    }
}

fun main() = runBlocking<Unit> {
    println("Calling simple function...")
    val flow = simple()
    println("Calling collect...")
    flow.collect { value -> println(value) } 
    println("Calling collect again...")
    flow.collect { value -> println(value) } 
}

我在collect上得到了错误。

This is an internal kotlinx.coroutines API that should not be used from outside of kotlinx.coroutines. No compatibility guarantees are provided.It is recommended to report your use-case of internal API to kotlinx.coroutines issue tracker, so stable API could be provided instead

当我添加@InternalCoroutinesApi

@InternalCoroutinesApi
fun main() = runBlocking<Unit> {
    println("Calling simple function...")
    val flow = simple()
    println("Calling collect...")
    flow.collect { value -> println(value) }
    println("Calling collect again...")
    flow.collect { value -> println(value) }
}

我在collect的lambda(value -> println(value的函数)中得到一个错误,如下所示。

Type mismatch.
Required:
FlowCollector<Int>
Found:
([ERROR :  ]) → Unit
Cannot infer a type for this parameter. Please specify it explicitly.

我使用的是Kotlin版本1.4.21。

implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.2"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'

我是否做错了什么,导致无法在Android Studio中编译示例代码?

rjee0c15

rjee0c151#

答案是,否,collect不仅仅是内部的kotlinx.coroutines API。错误信息具有误导性。
根据@ir42的评论,add import kotlinx.coroutines.flow.collect解决问题。

附加信息,为什么我没有选择collectLatest作为答案

collectcollectLatest不同。
用这个例子

fun simple(): Flow<Int> = flow { // flow builder
    for (i in 1..3) {
        delay(100) // pretend we are doing something useful here
        emit(i) // emit next value
    }
}

fun main() = runBlocking<Unit> {
    // Launch a concurrent coroutine to check if the main thread is blocked
    launch {
        for (k in 1..3) {
            println("I'm not blocked $k")
            delay(100)
        }
    }
    // Collect the flow
    simple().collect { value -> println(value) } 
}

收集将产生

I'm not blocked 1
1
I'm not blocked 2
2
I'm not blocked 3
3

根据https://kotlinlang.org/docs/reference/coroutines/flow.html
但是collectLatest

fun simple(): Flow<Int> = flow { // flow builder
    for (i in 1..3) {
        delay(100) // pretend we are doing something useful here
        emit(i) // emit next value
    }
}

fun main() = runBlocking<Unit> {
    // Launch a concurrent coroutine to check if the main thread is blocked
    launch {
        for (k in 1..3) {
            println("I'm not blocked $k")
            delay(100)
        }
    }
    // Collect the flow
    simple().collectLatest { value -> println(value) } 
}

将产生

I'm not blocked 1
I'm not blocked 2
1
I'm not blocked 3
2
xienkqul

xienkqul2#

添加以下导入:

import kotlinx.coroutines.flow.collect
fgw7neuy

fgw7neuy3#

我终于找到了解决它的方法,在它几乎把我逼疯了。由于这里没有一个解决方案对我有效,我有一个特殊的情况,我正在处理一个多模块项目,collect()总是在到处抛出这个错误,甚至手动导入它也没有修复它。
解决这个问题的方法是显式地将协程依赖添加到我项目的所有模块build.gradle文件中,而不仅仅是应用程序的一个,甚至那些不使用协程的模块。

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2")
axzmvihb

axzmvihb4#

对于1.6.0-RC3和更高版本:
@InternalCoroutinesApi注解已从所有collect()函数中删除(参见this PR)。
这意味着我们不会再看到错误,也不需要导入

import kotlinx.coroutines.flow.collect

因为(连同another PR的更改)我们现在可以直接使用collect()成员函数了。

bkhjykvo

bkhjykvo5#

API在kotlinx协同程序的更新版本中发生了变化,不再是collect函数中的lambda,而是作为链中的最终调用。文档示例:

flow
  .onEach { value -> process(value) }
  .catch { e -> handleException(e) }
  .collect() // trigger collection of the flow
z5btuh9x

z5btuh9x6#

我只是将转换为同一个对象(这里是StateFlow),如下所示:

(flow as StateFlow).collect { value -> println(value) }
yhxst69z

yhxst69z7#

collect替换为collectLatest

相关问题