我是 Koltin 协程的新手,有时它会让人感到困惑。假设在我的视图模型中我正在收集如下流:
viewModelScope.launch A@{
uiState.collect { state ->
// Do something
}
}
只要 viewModelScope 可用,块 A 就应该收集状态。现在,如果我想在 collect 块内启动另一项作业怎么办?
我想如果我这样做
var jobBAlreadyLaunched = false
viewModelScope.launch A@{
uiState.collect { state ->
if (state.isOk && !jobBAlreadyLaunched) {
launch B@{
anotherState.collect { res->
jobBAlreadyLaunched = true
}
}
}
}
}
如果作业A取消,块B将被取消。所以我将代码更改为:
var jobCAlreadyLaunched = false
viewModelScope.launch A@{
uiState.collect { state ->
if (state.isOk && !jobCAlreadyLaunched) {
viewModelScope.launch C@{
anotherState.collect { res->
jobCAlreadyLaunched = true
}
}
}
}
}
在这种情况下,我认为块 C 绑定到 viewModelScope 并且独立于块 A 的协程范围,因此只要 viewModelScope 处于活动状态,协程 C 将继续工作。 这个概念总体上正确吗?
我想在 state.isOk 为 true 时启动协程 C 并让它收集 res 更新,直到视图模型处于活动状态,但我不确定此实现是否正确。
我认为如果块C被暂停,它不会暂停块A。这是正确的吗?
非常感谢您的帮助。
您对 B 和 C 之间不同行为的描述是正确的。
B 是 A 的子协程,因此当 A 取消时,B 也会被取消。另外,工作 A 在 B 完成之前不会完成。
C 是 B 的兄弟协程,将完全独立运行。由于
viewModelScope
是使用 SupervisorJob 构建的,因此 A 和 C 可以彼此独立地失败。
我认为如果C块被暂停,它不会暂停A块。这是正确的吗?
正确。对于 B 来说本质上也是如此,只不过当 A 到达其
launch
lambda 的末尾时,它仍然会等待启动的 B 完成才能被视为完成。