我对在协程中使用 withContext 感到困惑。我正在使用 IO 调度程序在挂起函数中调用 withContext 。在这种情况下,在某些情况下,协程会因为视图模型被破坏而被取消。所以我想到了使用withContext改变coroutineContext的想法。但我发现了不同的方法。现在我很困惑哪种方法最好。我在下面分享这些方法。帮助我从下面的示例中找到最佳方法,并让我其中任何一个都有反模式。
class MyRepositoryOne {
private val scope= CoroutineScope(SupervisorJob())
suspend fun reset()= withContext(scope.coroutineContext){}
}
class MyRepositoryTwo {
private val job= SupervisorJob()
suspend fun reset()= withContext(job){}
}
class MyRepositoryThree {
suspend fun reset()= withContext(SupervisorJob()){}
}
class MyRepositoryFour {
suspend fun reset()= withContext(CoroutineScope(SupervisorJob()).coroutineContext){}
}
如果我理解正确的话,你想要一个比视图模型寿命更长的协程。不过,你的方法都无法做到这一点。
关键是协程的生存期与协程启动时的作用域相同。由于您的存储库公开了一个挂起函数,因此只能在协程已经运行时调用这些函数。可能是
viewModelScope.launch { ... }
创建的协程。不管你用 withContext
做什么,协程都会在 viewModelScope 被取消时被取消(这在视图模型被销毁时发生)。
如果您希望协程比视图模型寿命更长,您需要使用另一个作用域。在 Android 中,这应该是您的应用程序类中的作用域。您可以通过多种方式获取其中之一。如果您使用 Hilt 进行依赖项注入,您可以这样做:https://medium.com/androiddevelopers/create-an-application-coroutinescope-using-hilt-dd444e721528,否则请参阅此问题:Coroutine range on Application android 类.
然后您可以从存储库函数中删除
suspend
修饰符,并使用这个新的应用程序范围在存储库中启动一个新的协程。
不过,您不应该在存储库中创建新的协程范围,这使得协程正在运行的内容变得不透明。要么为存储库提供一个范围,以便它可以启动新的协程(此处为应用程序范围),要么在存储库中公开挂起函数,以便调用者可以决定使用哪个协程。