【问题标题】:Why this Kotlin Coroutine is freezing the interface?为什么这个 Kotlin 协程会冻结界面?
【发布时间】:2018-02-22 19:46:39
【问题描述】:

所以,我在“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 协程?

【问题讨论】:

    标签: android kotlin kotlin-coroutines


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 非常感谢马尔科。很好的答案。
    猜你喜欢
    • 2011-11-13
    • 1970-01-01
    • 2012-01-12
    • 2021-10-18
    • 1970-01-01
    • 2020-02-23
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多