简体   繁体   English

Kotlin 协程不执行多个挂起函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM