如何在主线程上使用协同程序GlobalScope?

Ben*_*654 6 android kotlin kotlin-coroutines

我试图在0.30.0中使用最新的协同程序,并且无法弄清楚如何使用新的作用域.在原始的协同程序中,我可以使用UI或CommonPool设置上下文,一切正常.

现在我正在尝试在从房间数据库中读取时在我的ViewModel中使用GlobalScope,然后我想将返回的值赋给我的LiveData对象.

我尝试设置LiveData值时收到以下错误

java.lang.IllegalStateException:无法在后台线程上调用setValue

fun getContact() {
        GlobalScope.launch {
            val contact = contacts.getContact() // suspended function
            withContext(Dispatchers.Default) { phoneContact.value = contact }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我只看到调度员的默认,无限和IO,而且没有一个工作,我无法弄清楚我做错了什么?我对主线程的选择在哪里?

Mar*_*nik 25

您通过添加依赖项解决了您的直接问题,但是让我添加一个关于您的使用情况的说明GlobalScope.

使用GlobalScopein生产代码是反模式.这是出于类似的原因,例如 runBlocking,使快速实验变得容易.由于应用程序组件的生命周期复杂,您应该特别避免在Android上使用它.

如果您从Android事件处理程序启动协程,则应使用当前的Activity作为其协程范围.这将确保您的协程在活动被销毁时被取消.没有它,协程将继续,指的是现在已经死亡的活动.

这是一个根据文档CoroutineScope改编的示例,它显示了如何将您的活动用作协程范围:

class MyActivity : AppCompatActivity(), CoroutineScope {
    // Sets up the default dispatcher and the root job that we can use to centrally
    // cancel all coroutines. We use SupervisorJob to avoid spreading the failure
    // of one coroutine to all others.
    override val coroutineContext: CoroutineContext =
            Dispatchers.Main + SupervisorJob()

    override fun onDestroy() {
        super.onDestroy()
        coroutineContext[Job]!!.cancel()
    }

    // this.launch picks up coroutineContext for its context:
    fun loadDataFromUI() = this.launch {
        // Switch to the IO dispatcher to perform blocking IO:
        val ioData = withContext(Dispatchers.IO) {
            // blocking I/O operations
        }
        draw(ioData) // use the data from IO to update UI in the main thread
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用a ViewModel,请将其用作范围并从中取消主作业onClear.

如果您正在从后台工作中完成工作,请使用您的JobService实现作为范围和用途onStartJob以及onStopJob我们使用onCreateonDestroy上面的方式.

  • @hippietrail`实现'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1'``实现“org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1”` (2认同)

Ben*_*654 7

我在gradle文件中缺少了coroutines的Android部分

实现"org.jetbrains.kotlinx:kotlinx-coroutines-android:0.30.0"

有一次,Dispatchers.Main出现了