我正在尝试找出如何启动协程。我希望它依次调用两个暂停函数。
我阅读的第一份文档说是这样做的:
class Something {
fun initialize() {
launch {
suspendFun1()
suspendFun2()
}
}
但是Android Studio找不到launch
方法。然后我了解到official coroutine docs建议使用GlobalScope.launch
:
class Something {
fun initialize() {
GlobalScope.launch {
suspendFun1()
suspendFun2()
}
}
但是我在this post中读到,您不应该使用GlobalScope.launch
。
因此,我找到了另一个blog post,解释说我需要一个CoroutineScope来调用launch
。但这并没有说明如何构建一个。
然后,我发现这个blog post解释了如何通过在类上实现CoroutineScope来为Activity和ViewModel构建对象:
class Something : CoroutineScope {
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
fun initialize() {
job = Job()
launch {
suspendFun1()
suspendFun2()
}
}
然后我读了blog post,说我不应该实现CoroutineScope
class Something {
protected val scope = CoroutineScope(
Job() + Dispatchers.Main
)
fun initialize() {
scope.launch {
suspendFun1()
suspendFun2()
}
}
但是我不确定我是否了解Job() + Dispatchers.Main
的含义,因为这似乎也可以工作:
class Something {
protected val scope = CoroutineScope(Dispatchers.Main)
fun initialize() {
scope.launch {
suspendFun1()
suspendFun2()
}
}
有人可以简单地向我解释最好的方法吗?如上吗?我确定已经有人问过这个问题,因此对这个重复的问题我深表歉意。但是如您所见,对此尚无明确答案。我想听听您的意见。
答案 0 :(得分:1)
最后两种解决方案都可以。如果您传递不带上下文的上下文,则CoroutineScope(context: CoroutineContext)
将创建一个空的Job
。
指定job + dispatcher
是一种更为明确的构建方式,因为在某些情况下,您可能想使用SupervisorJob
来防止在子作业之一失败时取消整个作用域。
关于在Activities
和ViewModels
中构建作用域,您无需声明自己的作用域,而可以通过导入KTX片段模块来使用KTX库中内置的作用域:
// add to your apps dependencies
implementation 'androidx.fragment:fragment-ktx:1.2.0-rc02'
现在在Activity
和Fragment
内,您可以使用lifecycleScope
,并在ViewModel
和viewModelScope
内使用SupervisorJob + Dispatchers.Main.immediate
支持的范围并在其各自的生命周期被破坏时自动取消。
答案 1 :(得分:0)
我有Coroutines.kt
object Coroutines {
fun main(work: suspend (() -> Unit)) {
CoroutineScope(Dispatchers.Main).launch {
work()
}
}
}
然后我通过调用Couroutines.main在我的视图模型中使用它
答案 2 :(得分:0)
我陷入了非常相似的困境,OP 出色地捕捉到了新手对各种资源的困惑。就我而言,除了创建自己的 CoroutineScope
之外,我别无选择,因为我需要一个长期运行的作用域,它的生命周期与应用进程的生命周期一样长(它使用挂起函数处理与 Retrofit 的交互),并且它一直存在在 Android 库中,无法访问 ViewModel
和其他 LifecycleOwner
项。
/**
* A [CoroutineScope] for HTTP cloud implementations to launch coroutines in. A coroutine
* dispatcher is not specified because Retrofit will switch to its own custom dispatcher
* when performing suspending network calls.
*/
internal val networkingScope = CoroutineScope(SupervisorJob())