简体   繁体   English

取消 viewModelScope 并在以后重新使用它

[英]Cancel viewModelScope and re-use it later on

I'm using Coroutines for dealing with async jobs:我正在使用Coroutines来处理异步作业:

viewModelScope.launch {
    val userResponse = getUsers() //suspendable function 
}

What I want to do is stop all existing/ongoing coroutine jobs.我想要做的是停止所有现有/正在进行的协程作业。 Idea is that I click on different tabs.想法是我点击不同的标签。 If getUsers() takes up to 5 seconds and user clicks from User tab to Job tab, I want that existing API call is stopped and response is not observed.如果getUsers()最多需要 5 秒,并且用户从“用户”选项卡单击“作业”选项卡,我希望现有 API 调用停止并且未观察到响应。

I tried to do viewModelScope.cancel() , but that seems not to be working.我试图做viewModelScope.cancel() ,但这似乎不起作用。

Question is - how to cancel existing jobs on button click?问题是 - 如何在单击按钮时取消现有作业?

Define a reusable Job like following in the ViewModel class:ViewModel类中定义一个可重用的Job ,如下所示:

private var job = Job()
    get() {
        if (field.isCancelled) field = Job()
        return field
    }

Pass it to all of launch coroutine builders as the parent Job :将它作为父Job传递给所有启动协程构建器:

viewModelScope.launch(job) {
    val userResponse = getUsers()
}

viewModelScope.launch(job) {
    // some other work
}

...

On button click, just cancel the parent job:单击按钮时,只需取消父作业:

fun cancelAll() {
    job.cancel()
}

You can get its Job through its CouroutineContext like this:你可以像这样通过它的CouroutineContext得到它的Job

viewModelScope.coroutineContext[Job]

To stop all existing/ongoing coroutine jobs you can call its cancel method:要停止所有现有/正在进行的协程作业,您可以调用其cancel方法:

viewModelScope.coroutineContext[Job]?.cancel()

If you need to start other coroutines eventually then call its cancelChildren method instead:如果您最终需要启动其他协程,则改为调用其cancelChildren方法:

viewModelScope.coroutineContext[Job]?.cancelChildren()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM