Home > Software engineering >  problem with kotlin coroutine runBlocking and stateIn
problem with kotlin coroutine runBlocking and stateIn

Time:08-24

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking

val numbers: StateFlow<Int> = (1..100).asFlow()
    .onEach { delay(100) }
    .let {
        runBlocking {
            it.stateIn(this)
        }
    }

fun main(){
    println("hello")
    println(numbers.value)
    println("bye")
}

I expect that main function finish only in 100ms (wait for first emission) but second print happens when all items emitted (takes about 100*100 ms) and also prints last item instead of first one!

am I missing something or it is a bug ?

CodePudding user response:

That’s expected behaviour when you use runBlocking, because runBlocking won’t return until all of its child jobs have completed.

In other words, the numbers property won’t return a value until the entire flow has terminated. This is because calling stateIn(scope) launches a job inside the scope that collects all the items from the flow. You can see where this happens in the source code.

If you want to allow the numbers flow to emit values concurrently with your main function, you'll need to use a scope in which both functions can run together. For example, you could call runBlocking in the main function, and pass the scope as a receiver for the numbers property:

val CoroutineScope.numbers: StateFlow<Int> get() = (1..100).asFlow()
    .onEach { delay(100) }
    .let {
        it.stateIn(this)
    }

fun main() = runBlocking {
    println("hello")
    println(numbers.value)
    println("bye")
}
  • Related