[英]Kotlin Coroutine doesn't execute multiple suspend functions
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.)我有一个简单的挂起函数序列(在 Android Kotlin 中),我想按顺序运行(一旦第一个完成,然后运行第二个。)
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)!编辑:我试图排除一些可能的问题,似乎起作用的是首先完全清空 function(空体)!
The problem is that my firstFunction actually works, it has something like this:问题是我的 firstFunction 实际上有效,它有这样的东西:
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?如果第一次暂停 function 已经完成,是否会以某种方式
launch
永远不知道?
I assume that localProtoDataStore.preferences
returns a Flow
and it seems infinite, because it listens to the preferences changes.我假设
localProtoDataStore.preferences
返回一个Flow
并且它看起来是无限的,因为它会监听偏好的变化。 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.在此类
Flow
上调用collect()
将暂停任何 function 直到收集完成(但它从未完成,因为Flow
是无限的)或执行协程的CoroutineScope
被取消。
So to execute the second function you have a couple of options.因此,要执行第二个 function,您有几个选择。 For example you can get only one value from the
Flow
:例如,您只能从
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:或者您可以摆脱在
firstSuspendFunction()
中使用Flow
并只检索首选项中的当前数据:
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
:或者您可以启动另一个协程来从
Flow
收集数据:
scope.launch(Dispatchers.IO) {
launch {
firstSuspendFunction()
}
secondSuspendFunction()
}
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 .为父协程中的每个function调用启动新的协程,以便它们可以单独从 Flow 收集数据,而不会陷入父协程的暂停状态。 For example, in your case:
例如,在您的情况下:
GlobalScope.launch(Dispatchers.IO) {
launch {
firstSuspendFunction()
}
launch {
secondSuspendFunction()
}
....
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.