首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候使用withContext?

什么时候使用withContext?
EN

Stack Overflow用户
提问于 2020-09-25 08:08:31
回答 1查看 5.6K关注 0票数 10

目前,我的代码如下所示,我有一个ViewModel,它调用存储库进行一些后台计算并返回结果。

ViewModel函数与viewModelScope.launch(Dispatchers.IO)一起运行,然后存储库--一个是suspend函数。

我是否必须使用返回withContext{}来确保所有事情都按顺序完成?我检查了一下,它确实是连续的,但是在文档中我发现它不一定是必要的。

EN

回答 1

Stack Overflow用户

发布于 2020-09-25 08:34:18

让我们首先从viewModelScope的源代码中剖析它。它使用CouroutineScope的自定义实现。上下文由一个SupervisorJob和一个Dispatchers.Main调度器组成。这确保协同线是在主线程上启动的,并且它的失败不会影响范围内的其他协同机制。

代码语言:javascript
复制
CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))

几个值得探讨的例子。

代码语言:javascript
复制
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

我检查了一下,它确实是连续的,但是在文档中我发现它不必是这样的。

withContext()是一个暂停操作,协同线将挂起直到它完成,然后继续前进。从上面的第三个例子可以看出这一点。

总之,viewModelScope将使用主线程执行一个协同线,其取消不会影响其他路径。当您希望以挂起的方式在主线程上执行繁重的任务时,请使用withContext;使用适当的dispatcher进行调度。Kotlin 指南值得一读。

编辑:

将下面的代码视为单个执行单元。这说明了这样一个事实:当使用withContext()时,调用线程正在挂起,但它没有被阻塞,这允许它继续并获得其他一些挂起的工作。我们对输出记录器的交错感兴趣。

代码语言:javascript
复制
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!
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64060268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档