android - 如何等待协程结束
问题描述
我在下面有一些代码。延迟(3000)只是一个长循环(或循环)的替代品。我期望循环完成println(res)
后将打印“Some String”,然后启用button
. 但在现实生活中println(res)
打印一个空字符串并button
在我单击它时同时启用。我的问题是:我如何才能等待协程结束,并且只有在协程运行完成后才能println(res)
等待button.isEnabled = true
.
private var res: String = ""
private suspend fun test(): String {
delay(3000) // delay - just replacement for long loop
return "Some String" // String received after loop
}
fun onClick(view: View) {
res = ""
button.isEnabled = false
GlobalScope.launch {
res = withContext(Dispatchers.Default) {
test()
}
}
println(res) // 1. trying to get string received after loop, but not working
button.isEnabled = true // 2. button must be enabled after loop in cycle, but it's not waiting till end of loop
}
解决方案
这里要理解的主要内容是协程中的代码默认情况下是按顺序执行的。 即协程相对于“兄弟”代码异步执行,但协程内的代码默认同步执行。
例如:
fun DoSometing () {
coroutineA {
doSomethingA1()
doSomethingA2()
}
some additional code
}
Corroutine A 将执行与一些附加代码相关的异步, 但 doSomethingA2 将在 doSomethingA1 完成后执行。
这意味着,在协程中,下一段代码将在前一段代码完成后执行。因此,无论您想在协程完成时执行什么,您只需将其放在该协程的末尾并声明您要在其中执行它的上下文( withContext )。
当然,如果您在协程(如另一个协程)中启动另一段异步代码,则例外。
编辑:如果你需要从协程更新 UI,你应该在主上下文中执行它,即你会有这样的东西:
GlobalScope.launch (Dispatchers.IO) {
//do some background work
...
withContext (Dispatchers.Main) {
//update the UI
button.isEnabled=true
...
}
}
推荐阅读
- hive - Hive failed error in semantic analysis invalid table alias or column reference
- google-bigquery - Google BigQuery 中的 FROM_HEX 返回的结果与公共文档中的结果不同
- javascript - 键值对,将数组作为值
- django-rest-framework - 如何在 DRF 的父序列化程序中获取和显示所有子对象
- javascript - 将对象值数组映射到 Typescript 中的接口类型
- angular7 - 如何在 Angular 7 中创建动态多步骤侧边栏菜单?
- pdf - 使用java企业版读取PDF文件的困难使用PDFBox
- office-js - 检测 Outlook 加载项
- azure - Azure ML Studio 编辑元数据不起作用
- node.js - 如何通过 configureWebpack 向 Vuepress 组件公开 Node 环境变量?