android - 在挂起函数上调用 await() 无法正常工作
问题描述
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-示例
您可以从 api 调用中创建一个 Deferred 对象列表并等待每个对象。
推荐阅读
- c - 使用 scanf 和无字符串库函数的 C 回文
- python - 如何修复我在验证步骤中使用的代码?
- firebase - 如何修复 Xamarin 和 Firebase 中的“com.google.firebase.messaging 包不存在”错误
- amazon-web-services - 无法检索 EC2 实例的默认 Windows 管理员密码
- javascript - 反应原生返回图像功能
- python - 如何在 Django 或 python 中将字符串转换为对象?
- java - 如何检测用户何时真正选择了 ComboBox 的菜单项?
- php - 如何获取对象而不是数组,例如 FETCH_OBJECT 而不是 FETCH_ASSOC
- r - 具有多个自变量和 1 个分类变量的 Ancova
- css - 为什么我的 custom.css 文件没有修改我的 materialize.css?