英文:
What coroutine scope should I use in this case?
问题
I have a view model where I use viewModelScope
and everything works perfect in there. Then, I have a class shared by many view models (injected in the constructor). Inside that class I need to call suspend methods and I don't know what's the correct coroutine scope to use.
Right now I'm using GlobalScope
but it doesn't sound quite right, I feel the scope of execution should be guided by the owner of this class instance (the view model). I don't understand why if view model uses viewModelScope
this injected class should use GlobalScope
if not necessary.
I'm quite new with Kotlin so I might be missing something obvious.
英文:
I have a view model where I use viewModelScope
and everything works perfect in there. Then, I have a class shared by many view models (injected in the constructor). Inside that class I need to call suspend methods and I don't know what's the correct coroutine scope to use.
Right now I'm using GlobalScope
but it doesn't sound quite right, I feel the scope of execution should be guided by the owner of this class instance (the view model). I don't understand why if view model uses viewModelScope
this injected class should use GlobalScope
if not necessary.
I'm quite new with Kotlin so I might be missing something obvious.
答案1
得分: 2
以下是翻译好的部分:
唯一可以在多个ViewModel之间共享的范围是Singleton范围,因此我假设所讨论的类是以这种方式提供的(否则每个ViewModel都会获得一个新实例,然后可以使用VM范围)。您可以创建一个共享的监督作业,以下是我通常的做法:
@Singleton
open class CoroutinesDispatchers @Inject constructor() {
open val IO: CoroutineDispatcher = Dispatchers.IO
open val Main: CoroutineDispatcher = Dispatchers.Main
open val Default: CoroutineDispatcher = Dispatchers.Default
open val Unconfined: CoroutineDispatcher = Dispatchers.Unconfined
}
这样可以在单元测试中交换调度程序,并遵循不直接使用Dispatchers.XX
的一般建议。实际的范围如下提供:
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class DefaultCoroutineScope
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class UICoroutineScope
@Module
@InstallIn(SingletonComponent::class)
object CoroutinesModule {
@Provides
@Singleton
@DefaultCoroutineScope
fun defaultCoroutineScope(dispatchers: CoroutinesDispatchers): CoroutineScope = CoroutineScope(
SupervisorJob() + dispatchers.Default
)
@Provides
@Singleton
@UICoroutineScope
fun uiCoroutineScope(dispatchers: CoroutinesDispatchers): CoroutineScope = CoroutineScope(
SupervisorJob() + dispatchers.Main
)
}
然后,您只需注入您需要的范围 - 当然,您可以使用其他调度程序(例如IO)或根据需要在启动协程后更改调度程序。基本上,您得到的是一种更可控的方式中的一种全局范围。
英文:
The only scope that can be shared between multiple ViewModels is the Singleton scope, so I assume the class in question is provided as such (otherwise you'd get a new instance for every ViewModel and then it's fine to use the VM scope). What you could do is creating a shared supervisor job, here's how I usually go about that:
@Singleton
open class CoroutinesDispatchers @Inject constructor() {
open val IO: CoroutineDispatcher = Dispatchers.IO
open val Main: CoroutineDispatcher = Dispatchers.Main
open val Default: CoroutineDispatcher = Dispatchers.Default
open val Unconfined: CoroutineDispatcher = Dispatchers.Unconfined
}
^^ this one allows you to swap out the dispatchers in unit tests and follows the general recommendation not to use Dispatchers.XX
directly. The actual scopes are provided as follows:
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class DefaultCoroutineScope
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class UICoroutineScope
@Module
@InstallIn(SingletonComponent::class)
object CoroutinesModule {
@Provides
@Singleton
@DefaultCoroutineScope
fun defaultCoroutineScope(dispatchers: CoroutinesDispatchers): CoroutineScope = CoroutineScope(
SupervisorJob() + dispatchers.Default
)
@Provides
@Singleton
@UICoroutineScope
fun uiCoroutineScope(dispatchers: CoroutinesDispatchers): CoroutineScope = CoroutineScope(
SupervisorJob() + dispatchers.Main
)
}
Then you just inject the scope you need - you could of course use other dispatchers (e.g. IO) or change the dispatcher after launching a coroutine according to your needs. Basically what you get is a kind of a GlobalScope in a more controllable manner.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论