Is Kotlin Flow's Collect is only internal kotlinx.coroutines API?

KotlinKotlin Flow

Kotlin 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionElyeView Question on Stackoverflow
Solution 1 - KotlinElyeView Answer on Stackoverflow
Solution 2 - KotlinRissmon SureshView Answer on Stackoverflow
Solution 3 - KotlinPeter FView Answer on Stackoverflow
Solution 4 - KotlinEpicPandaForceView Answer on Stackoverflow