我们用coroutineContext和Job调用withContext有什么区别?

问题描述 投票:0回答:1

我对在协程中使用 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){}
}
kotlin kotlin-coroutines coroutinescope withcontext
1个回答
0
投票

如果我理解正确的话,你想要一个比视图模型寿命更长的协程。不过,你的方法都无法做到这一点。

关键是协程的生存期与协程启动时的作用域相同。由于您的存储库公开了一个挂起函数,因此只能在协程已经运行时调用这些函数。可能是

viewModelScope.launch { ... }
创建的协程。不管你用
withContext
做什么,协程都会在 viewModelScope 被取消时被取消(这在视图模型被销毁时发生)。

如果您希望协程比视图模型寿命更长,您需要使用另一个作用域。在 Android 中,这应该是您的应用程序类中的作用域。您可以通过多种方式获取其中之一。如果您使用 Hilt 进行依赖项注入,您可以这样做:https://medium.com/androiddevelopers/create-an-application-coroutinescope-using-hilt-dd444e721528,否则请参阅此问题:Coroutine range on Application android 类.

然后您可以从存储库函数中删除

suspend
修饰符,并使用这个新的应用程序范围在存储库中启动一个新的协程。

不过,您不应该在存储库中创建新的协程范围,这使得协程正在运行的内容变得不透明。要么为存储库提供一个范围,以便它可以启动新的协程(此处为应用程序范围),要么在存储库中公开挂起函数,以便调用者可以决定使用哪个协程。

© www.soinside.com 2019 - 2024. All rights reserved.