android - 在挂起函数上调用 await() 无法正常工作

标签 android kotlin coroutine

private val coroutineSupervisor = SupervisorJob()
protected val dispatcherProvider = CoroutineDispatcherProvider()
protected val viewModelScope = CoroutineScope(dispatcherProvider.main + coroutineSupervisor)

class CoroutineDispatcherProvider {

    val main: CoroutineDispatcher
        get() = Dispatchers.Main

    val background: CoroutineDispatcher
        get() = Dispatchers.IO
}

viewModelScope.launch {
    ...
    runBlocking {
        async { firstNumber() }.await()
        async { secondNumber() }.await()
        async { test() }.await()
        async { thirdNumber() }.await()
    }
}

suspend fun firstNumber(): Int {
    delay(3_000) // 3 seconds delay
    return 5
}
suspend fun secondNumber(): Int {
    delay(5_000) // 5 seconds delay
    return 8
}
suspend fun thirdNumber(): Int {
    delay(7_000) // 7 seconds delay
    return 10
}

suspend fun test() {
    withContext(dispatcherProvider.background) {
        ...
    }
}

前几天开始学习协程,看到了一些奇怪的东西。 firstNumber、secondNumber 和 thirdNumber 函数按应有的方式运行 - 延迟完成,然后下一个函数执行 - 以正确的顺序执行,但 test() 没有。它会在很晚之后返回值,并且在发生这种情况时 runBlocking 已经完成。我想确保它得到结果,然后以某种方式在其他请求中使用它。是因为我在那里使用了某种错误的调度程序还是什么?

最佳答案

事情是这样的。当您通过 async 和 await 调用 test() 方法时,您期望的是等待它完成。

但是由于您在测试方法中有一个回调流程(apiclient 调用),它会在从服务器获得响应之前立即返回并退出测试方法。当响应准备好时,稍后调用回调 lambda。到这个时候运行阻塞已经完成。

所以你应该做的是将你的回调转换为协程。 Codelabs-example

并且您可以从 api 调用中创建一个延迟对象列表并等待每个对象。

关于android - 在挂起函数上调用 await() 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55587120/

相关文章:

android - JUnit 本地测试 - 'Unresolved reference: test'

android - AudioManager 的低级别流类型有什么区别?

java - 图片检索速度慢

android - applicationContext recycleview 元素的未解决引用(适用于 android 的 kotlin 应用程序)

java - 安装apk后我可以下载android库吗?

kotlin - 在 Kotlin 中,如何传递参数以便异步作用域保留它?

java - 发送原始 RIL 请求

拒绝时授予 Android 12 BLUETOOTH_CONNECT 权限

C 嵌套开关 : outer switch's case inside inner switch

c# - 协程中的 Vector3.Lerp 在 Unity3D 上无法正常工作