jean
04/24/2023, 11:49 AMfun initialize() {
coroutineScope.launch {
<http://log.info|log.info>(TAG, "Start flow collection")
startFlowCollection(vim.value)
<http://log.info|log.info>(TAG, "Done with initialization")
}
}
suspend fun startFlowCollection() = supervisorScope {
launch { collectFromCallbackFlow1() }
launch { collectFromCallbackFlow2() }
}
But I never get “Done with initialization”. I understand callback flows never finish so I collect them inside launch
to not suspend forever. But it looks like it is suspending forever so I don’t know what I’m doing wrong here.Joffrey
04/24/2023, 11:50 AMCoroutineScope
for the 2 launch
-es in startFlowCollection
? This shouldn't compile as-is, unless startFlowCollection
is a method in a class that implements CoroutineScope
itself (which is unlikely)jean
04/24/2023, 12:03 PMcoroutineScope
comes from CoroutineScope(SupervisorJob() + <http://Dispatchers.IO|Dispatchers.IO>)
. I tried with suspend fun initialize
but it didn’t work neither, I though it might be due to the scope being cancelled (the code is part from an android app and initialize was called from a lifecycle scope) so I gave the class containing initialize
its own coroutine scopeJoffrey
04/24/2023, 12:03 PMlaunch
calls inside startFlowCollection
jean
04/24/2023, 12:03 PMjean
04/24/2023, 12:04 PMsupervisorScope
thereJoffrey
04/24/2023, 12:06 PMsupervisorScope { .. }
here gives a boundary to the lifetime of the 2 launch calls. startFlowCollection
will only return once the 2 launched coroutines are complete, which never happens if collectFromCallbackFlowN()
never completesjean
04/24/2023, 12:06 PMJoffrey
04/24/2023, 12:09 PMlaunch
directly inside initialize
. They would be part of the coroutine scope of the parent launch
call. It has the same property: it will not complete until the child coroutines are done. So you would get your "Done with initialization" log, but the launched coroutine would still be running. It might be what you want. I don't know. If your definition of "initialization is done" is "the collecting coroutines are launched" (not done!) then it's fine. But then another way to fix it is to just put the log outside the launch
in initialize
jean
04/24/2023, 12:13 PMuli
04/25/2023, 11:57 AMstartFlowCollection
to be suspend fun. Make it an extension fun on CoroutineScope and then just call launch (as in this.launch). Then you’ll not be waiting for the new coroutinesJoffrey
04/25/2023, 11:58 AMfun initialize() {
<http://log.info|log.info>(TAG, "Start flow collection")
coroutineScope.launch { collectFromCallbackFlow1() }
coroutineScope.launch { collectFromCallbackFlow2() }
<http://log.info|log.info>(TAG, "Done with initialization")
}
because there doesn't seem to be a need for an outer launchuli
04/25/2023, 12:04 PMfun initialize() {
coroutineScope.launch {
<http://log.info|log.info>(TAG, "Start flow collection")
startFlowCollection(vim.value)
<http://log.info|log.info>(TAG, "Done with initialization")
}
}
fun CorotuineScope.startFlowCollection() {
launch { collectFromCallbackFlow1() }
launch { collectFromCallbackFlow2() }
}
But as @Joffrey pointed out, as startFlowCollection
actually never was actually suspending an now no longer is a suspend fun. you can also call it without an outer launch. All you need is a scope
fun initialize() {
<http://log.info|log.info>(TAG, "Start flow collection")
coroutineScope.startFlowCollection(vim.value)
<http://log.info|log.info>(TAG, "Done with initialization")
}