Is Kotlin Flow's Collect is only internal kotlinx.coroutines API?
KotlinKotlin FlowKotlin Problem Overview
Taking the direct example from 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) }
}
I got the error on 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
When I add @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) }
}
I get an error in the collect
's lambda (function of value -> println(value
) as below
Type mismatch.
Required:
FlowCollector<Int>
Found:
([ERROR : ]) → Unit
Cannot infer a type for this parameter. Please specify it explicitly.
I am using Kotlin version 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'
Did I do anything wrong that I cannot compile the example code in Android Studio?
Kotlin Solutions
Solution 1 - Kotlin
The answer is, NO, collect
is not only internal kotlinx.coroutines API. The error message is misleading.
As per @ir42's comment, add import kotlinx.coroutines.flow.collect
solve the problem.
Additional info, why I didn't pick collectLatest
as the answer
collect
and collectLatest
is different.
Using this example
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) }
}
Collect will produce
I'm not blocked 1
1
I'm not blocked 2
2
I'm not blocked 3
3
as per https://kotlinlang.org/docs/reference/coroutines/flow.html
But 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) }
}
will produce
I'm not blocked 1
I'm not blocked 2
1
I'm not blocked 3
2
Solution 2 - Kotlin
Add below import:
import kotlinx.coroutines.flow.collect
Solution 3 - Kotlin
For version 1.6.0-RC3
and newer:
The @InternalCoroutinesApi
annotations have been removed from all collect()
functions (see this PR).
That means we won't see the error anymore and also won't need the import
import kotlinx.coroutines.flow.collect
anymore because (together with the changes of another PR) we can now use the collect()
member function directly.
Solution 4 - Kotlin
Replace collect
with collectLatest
.