4

所以,我在“onBindViewHolder”回收器的适配器方法中运行了这段代码:

 launch(UI) {
            val bitmapDrawable = loadLargeBitmapDrawable()          
            imageView.setImageDrawable(bitmapDrawable)
  }

这使我的应用程序冻结了几秒钟,锁定了我的主线程。

但后来我改成这样:

launch { // <- I removed the "UI"
            val bitmapDrawable = loadLargeBitmapDrawable()  

            launch(UI) { //Launch the UI coroutine inside the other
                imageView.setImageDrawable(bitmapDrawable)
            }      

  }

为什么会这样?协程的目的是在同一个线程(UI)中使事物异步,对吗?有人可以解释一下为什么我必须在另一个协程范围内运行 UI 协程?

4

1 回答 1

13

协程的目的是在同一个线程(UI)中使事物异步,对吗?

你认为协程的魔力比实际的要多。如果你的loadLargeBitmapDrawable()函数不是可挂起的,而是简单地占用它的线程直到完成,那么 Kotlin 对此无能为力。当您说 时launch(UI),您命令该函数在 UI 线程上运行。

您的第二个示例在CommonPool上下文中执行(这是默认设置),然后将任务发布到 UI 线程;一种更自然的说法是这样的(我在我的代码中使用它,目的与您完全相同):

launch(UI) {
    val bitmapDrawable = withContext(CommonPool) {
        loadLargeBitmapDrawable() 
    }
    imageView.setImageDrawable(bitmapDrawable)
}

withContext将暂停你在 UI 线程上启动的协程,将重量级操作提交到公共线程池,然后在 UI 线程上恢复协程及其结果。现在您可以将位图推送到imageView.

于 2018-02-22T20:19:07.187 回答