Hello, I have a hot flow (MutableSharedFlow) and was wondering why I'm required to launch a new coro...
c
Hello, I have a hot flow (MutableSharedFlow) and was wondering why I'm required to launch a new coroutine from a new scope when calling collect for the logic to continue? e.g
Copy code
suspend fun func1() = CoroutineScope(Dispatchers.Default).launch {
    func2()
    println("Not called")
}
suspend fun func2() = coroutineScope {
    launch {
        someFlow.collect { logic.invoke(it) }
    }
}
e
Because MutableSharedFlow is hot, it "never" closes. Collect is like an infinite for loop that will keep collecting until the last item is emitted. In a Cold Flow of 1,2,3 it will collect 3 times and then close and Not Called will be printed. But in a hot flow (shared or state flow), it stays active even after emitting N objs. So your collect function is waiting for the next item to be emitted See: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-shared-flow/
Shared flow never completes. A call to Flow.collect on a shared flow never completes normally, and neither does a coroutine started by the Flow.launchIn function. An active collector of a shared flow is called a subscriber.
c
I get that, I just assumed since I launched it in new coroutine it would handle collection on the new coroutine and allow existing one to continue but seems not. Is this because with the way I'm launching new coroutine, it's using context that has previous coroutine?
c
coroutineScope { }
will suspend as long as there are any other coroutines still running it in. Since the MutableSharedFlow never completes as mentioned above, the
launch { }
will continue to run forever, and thus the
coroutineScope { }
will also suspend indefinitely
c
Ah ok yeah makes sense, guess I'll launch in new scope or pass scope, thank you
c
What you probably meant to do instead is:
fun CoroutineScope.func2() = launch { }
. a function marked
suspend
implies that it will run until whatever inside it is finished. In contrast, by removing
suspend
and requiring a
CoroutineScope
receiver, you’re implying that the method is a “fire-and-forget” that will not suspend execution of the other stuff in the spot where it is called
c
Ah well that's an easy way to pass the scope lol, thank you 👍