【问题标题】:Kotlin coroutines CalledFromWrongThreadExceptionKotlin 协程 CalledFromWrongThreadException
【发布时间】:2017-11-02 10:28:15
【问题描述】:

我正在尝试使用 Kotlin 协程在后台运行一些繁重的工作。

但是我收到了这个错误信息,

'android.view.ViewRootImpl$CalledFromWrongThreadException: 只有 创建视图层次结构的原始线程可以触及其视图。'

fun setList() {
    media_image_list.adapter = imageListAdapter
    ...

    launch {
        val images = getImages(galleryPath)
        imageListAdapter.setItems(images)
    }
}




suspend private fun getImages(): MutableList<Image> {
    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    ...
}

如何让它在后台正确运行?

【问题讨论】:

  • 你能不能像这样在Unconfined模式下运行协程:launch(Unconfined)
  • @s1m0nw1 有效,如果与任何 UI 相关的作业有效,我是否需要使用 Unconfined?

标签: android kotlin coroutine


【解决方案1】:

我建议通过以下方式解决它:

首先,使用withContext 函数将您的“繁重工作”显式卸载到后台线程,如下所示:

// explicitly request it to be executed in bg thread
suspend private fun getImages(): MutableList<Image> = withContext(CommonPool) {
    val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    ...
}

然后,始终在 UI 线程中运行接触视图或其他 UI 对象的协程:

launch(UI) {
    val images = getImages(galleryPath)
    imageListAdapter.setItems(images)
}

【讨论】:

  • 我可以不使用'run(CommonPool)'吗?没有它,它就不会在后台线程中运行?
  • 您省略run(CommonPool),那么您的getImages 代码将在UI 线程中运行。如果你的getImages 使用 asynchronous 非阻塞 API 是可以的,但如果它使用阻塞线程的 API 就不行了。
猜你喜欢
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 2019-12-25
  • 2020-02-17
  • 2019-08-03
  • 2018-05-13
  • 2019-02-14
相关资源
最近更新 更多