- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
此代码使用旧的 Coroutines Api。如果您使用的是 kotlinx-coroutines 1.1.0 或更新版本,此代码对您没有用
原来的问题是:
我发现我的 Android 应用程序中的这段特定代码阻塞了 UI 线程:
runBlocking {
async(CommonPool) {
Thread.sleep(5000)
}.await()
}
textView.text = "Finish!"
我一直在为多项任务使用协程,它们从不阻塞 UI 线程,这可以在 the documentation 中阅读:
. Coroutines provide a way to avoid blocking a thread and replace it with a cheaper and more controllable operation: suspension of a coroutine
但奇怪的是,这段代码:
runBlocking {
async(CommonPool) {
launch(CommonPool) {
Thread.sleep(5000)
runOnUiThread { textView.text = "Finish!" }
}
}.await()
}
表现符合预期;不阻塞,等待五秒钟然后打印结果(之后我需要更新 UI,并且只有在 sleep
完成之后)
文档上说async
和launch
可以独立使用,不需要结合使用。事实上,async(CommonPool)
应该足够了。
那么这里到底发生了什么?为什么它只适用于 async+launch
?
[弃用警报] 此代码使用旧的 Coroutines Api。如果您使用的是 kotlinx-coroutines 1.1.0 或更新版本,请忽略此代码
我的完整示例代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button1.setOnClickListener {
runBlocking {
async(CommonPool) {
Thread.sleep(5000L)
}.await()
}
textView1.text = "Finally! I've been blocked for 5s :-("
}
button2.setOnClickListener {
runBlocking {
async(CommonPool) {
launch(CommonPool) {
Thread.sleep(5000L)
runOnUiThread { textView1.text = "Done! UI was not blocked :-)" }
}
}.await()
}
}
}
}
最佳答案
注意:这篇文章可以追溯到协程的预发布版本。我更新了调度员的姓名以匹配发布版本。
runBlocking
不是在 UI 线程上启动协程的方法,因为正如其名称所示,它会阻塞托管线程,直到协程完成。您必须在 Main
上下文中启动
它,然后切换到 Default
上下文以进行重量级操作。您还应该删除 async-await
对并使用 withContext
:
button1.setOnClickListener {
launch(Main) {
withContext(Default) {
Thread.sleep(5000L)
}
textView1.text = "Done! UI was not blocked :-)"
}
}
withContext
将挂起协程直到完成,然后在父上下文(即 Main
)中恢复它。
关于android - 为什么这个协程会阻塞 UI 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48663423/
我是一名优秀的程序员,十分优秀!