Reputation: 806
I have a simple sequence of suspend functions (in Android Kotlin) which I want to run in sequence (once first is finished, then run second.)
I tried doing something which seamed reasonable like this:
class SomeService {
init {
GlobalScope.launch(Dispatchers.IO) {
firstSuspendFunction()
secondSuspendFunction()
}
}
}
However, only first one is run, second is never executed. Why is that so?
Edit: I tried to rule out some possible issues, and what seemed to worked was by completely emptying first function (empty body)!
The problem is that my firstFunction actually works, it has something like this:
private suspend fun firstSuspendFunction() {
localProtoDataStore.preferences.collect {
someDataList.addAll(it.preferenceData)
}
}
Could it be that somehow launch
never knowns if first suspend function has finished?
Upvotes: 2
Views: 1466
Reputation: 951
Launch new Coroutine for each function call inside parent coroutine so that they can collect data from Flow individually without falling under suspension of parent coroutine. For example, in your case:
GlobalScope.launch(Dispatchers.IO) {
launch {
firstSuspendFunction()
}
launch {
secondSuspendFunction()
}
....
}
Upvotes: 0
Reputation: 30695
I assume that localProtoDataStore.preferences
returns a Flow
and it seems infinite, because it listens to the preferences changes. Calling collect()
on such Flow
will suspend any function until the collection is finished (but it never finished because the Flow
is infinite) or CoroutineScope
, which executed a coroutine, is canceled.
So to execute the second function you have a couple of options. For example you can get only one value from the Flow
:
private suspend fun firstSuspendFunction() {
localProtoDataStore.preferences.firstOrNull {
someDataList.addAll(it.preferenceData)
}
}
Or you can get rid of using Flow
in the firstSuspendFunction()
and just retrieve a current data in preferences:
private suspend fun firstSuspendFunction() {
val data = localProtoDataStore.preferences.get() // I don't know the exact name of the function, but the idea is clear
someDataList.addAll(data)
}
Or you can just launch another coroutine to collect data from the Flow
:
scope.launch(Dispatchers.IO) {
launch {
firstSuspendFunction()
}
secondSuspendFunction()
}
Upvotes: 0