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 startFlowCollectionjean
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 initializejean
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")
}