gpt4 book ai didi

android - 为什么这个协程会阻塞 UI 线程?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:26:11 24 4
gpt4 key购买 nike

弃用警报

此代码使用旧的 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 完成之后)

文档上说asynclaunch可以独立使用,不需要结合使用。事实上,async(CommonPool) 应该足够了。

那么这里到底发生了什么?为什么它只适用于 async+launch

更新(2021 年)

[弃用警报] 此代码使用旧的 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com