kotlinkotlin-coroutineskotlin-flow

Kotlin callbackFlow awaitClose trigger problem when delay


I couldn't understand something about callbackFlow. I have two implementation. There is only difference both of them is using delay or any other suspend function which includes delay. When I run 1. implementation, awaitClose block doesn't run but there is no problem when run the 2. implementation. Coroutine was canceled when I call the first function and in my code implementation needs first call.

I believe there is a logical explanation about that but I couldn't solve it.

1. Implementation

val callbackFlow = callbackFlow {
    send("Value")
    delay(100)
    awaitClose { println("Channel was closed") }
}

val firstValue = callbackFlow.first()
println(firstValue)

2. Implementation

val callbackFlow = callbackFlow {
    send("Value")
    awaitClose { println("Channel was closed") }
}

val firstValue = callbackFlow.first()
println(firstValue)

Solution

  • Flow.first() cancels the flow once the first value has been collected.

    In your case, it means that the awaitClose function is never reached.

    1. The call to callbackFlow.first() triggers flow collection
    2. The send("value") transmit value to the collector
    3. The collector cancels the flow
    4. Then, depending on your implementation
      1. The delay might have start, and is cancelled along the flow. The "awaitClose" function is never reached.
      2. Without delay, there's a chance that 'awaitClose' might register the lambda (and therefore execute it) faster than the collector cancels the flow.

    Note however, I'm not sure that the awaitClose is always reachable, even without delay. More research would be needed to give a definitive answer for that.