android - 何时使用 withContext?

标签 android kotlin kotlin-coroutines coroutine android-viewmodel

目前我的代码看起来像这样我有一个 ViewModel调用存储库进行一些后台计算并返回结果。
ViewModel 函数使用 viewModelScope.launch(Dispatchers.IO) 运行然后存储库一个是 suspend功能。
我必须使用 return withContext{}以确保一切都将按顺序进行?我检查了它确实是连续的,但是在文档中我发现它不一定是?

最佳答案

让我们剖析viewModelScope首先来自它的源代码。它使用 CouroutineScope 的自定义实现.上下文包括 SupervisorJobDispatchers.Main调度员。这确保了协程在主线程上启动,并且它的失败不会影响范围内的其他协程。

CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))
几个值得探索的例子。
viewModelScope.launch {
    Log.d("ViewModel", "Just viewModelScope: ${Thread.currentThread().name}")
}
// Output: Just viewModelScope: main

viewModelScope.launch(Dispatchers.IO) {
    Log.d("ViewModel", "IO viewModelScope: ${Thread.currentThread().name}")
}
// Output: IO viewModelScope: DefaultDispatcher-worker-3

viewModelScope.launch {
    Log.d("ViewModel", "viewModelScope thread: ${Thread.currentThread().name}")
    withContext(Dispatchers.IO) {
        delay(3000)
        Log.d("ViewModel", "withContext thread: ${Thread.currentThread().name}")
    }
    Log.d("ViewModel", "I'm finished!")
}
// Output: 
// viewModelScope thread: main
// withContext thread: DefaultDispatcher-worker-4

I checked and it is indeed sequential, but in the documentation i found that it doesn't have to be.

withContext()是一个暂停操作,协程将暂停直到完成,然后继续。从上面的第三个示例中可以明显看出这一点。
总之,viewModelScope将使用主线程执行一个协程,其取消不会影响其他协程。使用withContext当您想以挂起的方式从主线程执行繁重的任务时;使用适当的调度程序调度它。 Kotlin 协程 guide值得一读。
编辑:
将以下代码视为单个执行单元。这说明了使用 withContext() 时的事实。 ,调用者线程正在挂起,但它没有被阻塞,这允许它继续执行一些其他待处理的工作。输出记录器的交错是我们感兴趣的。
viewModelScope.launch {
    Log.d("ViewModel", "viewModelScope thread: ${Thread.currentThread().name}")
    withContext(Dispatchers.IO) {
        delay(3000)
        Log.d("ViewModel", "withContext thread: ${Thread.currentThread().name}")
    }
    Log.d("ViewModel", "I'm finished!")
}

viewModelScope.launch {
    Log.d("ViewModel", "I'm not blocked: ${Thread.currentThread().name}")
}

// Output: 
// viewModelScope thread: main
// I'm not blocked: main
// withContext thread: DefaultDispatcher-worker-2
// I'm finished!

关于android - 何时使用 withContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64060268/

相关文章:

java - 如何为 Retrofit 中的挂起功能创建调用适配器?

java - 如何通过 Html.fromHtml(text) 更改在 TextView 中加载的默认图像(占位符)

java - 未使用 QAndroidJniObject 调用的三个函数之一

kotlin - runBlocking 协程不会阻止 GlobalScope.launch (?)

android - 使用 mockito MVVM 模式在 android 中对 View 模型进行单元测试

java - 如何在 bottomsheetdialog 显示时退出应用程序

android - 在哪里可以找到 liveData 构建 block ?

Android:检查 View 是否以编程方式与父底部/顶部对齐

java - 将登录状态存储在 SharedPreference 中

Kotlin 协程压缩三个流程