为什么我不使用 viewModelScope(Dispatchers.IO).launch{ } 与 Kotlin?

huangapple go评论57阅读模式
英文:

Why don't I use viewModelScope(Dispatchers.IO).launch{ } with Kotlin?

问题

Code A是正确的,所以我认为Code B也是正确的,但实际上Code C可以编译,为什么?

Code B有什么问题?

Code A

CoroutineScope(Dispatchers.IO).launch {

}

Code B

viewModelScope(Dispatchers.IO).launch{

}

Code C

viewModelScope.launch(Dispatchers.IO){

}
英文:

The Code A is Ok, so I think Code B is Ok too, but in fact Code C can be compiled, why ?

What's wrong with Code B ?

Code A

CoroutineScope(Dispatchers.IO).launch {

}

Code B

viewModelScope(Dispatchers.IO).launch{

}

Code C

viewModelScope.launch(Dispatchers.IO){

}

答案1

得分: 2

很简单,CoroutineScopelaunch 是函数,viewModelScope 是属性。

  • CoroutineScope() 是一个函数,它接受一个 CoroutineContext 参数,用于启动它的作业。
  • launch 是一个函数,它接受一个可选的 CoroutineContext 参数,它将与其作用域的上下文合并,用于在其自己的协程中使用。
  • viewModelScope 是一个 CoroutineScope 的实例。它不是一个可调用的函数。
英文:

It’s as simple as CoroutineScope and launch are functions, and viewModelScope is a property.

  • CoroutineScope() is a function that takes a CoroutineContext parameter that it will use for jobs that it launches.
  • launch is a function that takes an optional CoroutineContext parameter that it will merge with its scope’s context to use in its own coroutine.
  • viewModelScope is an instance of a CoroutineScope. It is not an invokeable function.

答案2

得分: 1

Code A

Code B

Code C

解释

Code A

CoroutineScope(Dispatchers.IO).launch {
          
}

它有效,因为它创建了一个新的CoroutineScope,使用Dispatchers.IO并在该作用域中使用launch函数启动一个协程。

Code B

viewModelScope(Dispatchers.IO).launch{

}

它不起作用,因为viewModelScope是返回与ViewModel的生命周期绑定的CoroutineScope的属性。但是launch函数不是CoroutineScope类的成员,因此不能直接从viewModelScope中调用。

Code C

viewModelScope.launch(Dispatchers.IO){

}

它有效,因为viewModelScope是返回与ViewModel的生命周期绑定的CoroutineScope的属性。在这段代码中,launch函数是在由该属性返回的viewModelScope对象上调用的,并将Dispatchers.IO调度程序作为参数传递给launch函数。

希望现在清楚了。

英文:

Code A

Code B

Code C

Explanation

Code A

CoroutineScope(Dispatchers.IO).launch {

}

It works because it creates a new CoroutineScope with the Dispatchers.IO and launches a coroutine in that scope using the launch function.

Source code
为什么我不使用 viewModelScope(Dispatchers.IO).launch{ } 与 Kotlin?

Code B

viewModelScope(Dispatchers.IO).launch{

}

It does not work because viewModelScope is a property that returns a CoroutineScope tied to the lifecycle of the ViewModel. However the launch function is not a member of the CoroutineScope class, so it can not be called from viewModelScope directly.

Source code

为什么我不使用 viewModelScope(Dispatchers.IO).launch{ } 与 Kotlin?

Code C

viewModelScope.launch(Dispatchers.IO){

}

It does work because viewModelScope is a property that returns a CoroutineScope tied to the lifecycle of the ViewModel. In this code, the launch function is called on the viewModelScope object returned by the property, and the Dispatchers.IO dispatcher is passed as a parameter to the launch function.

Source code

为什么我不使用 viewModelScope(Dispatchers.IO).launch{ } 与 Kotlin?

Hope it's clear now.

答案3

得分: 1

In Code A,您正在使用CoroutineScope Builder创建自己的协程,通过提供Dispatcher,这是可以的,因为它允许您创建自己的协程。

In Code B,您正在使用viewModelScope,这是一个扩展属性,不像CoroutineScopeGlobalScope那样是协程构建器,正如下面的源代码所示。

    get() {
        val scope: CoroutineScope? = this.getTag(JOB_KEY)
        if (scope != null) {
            return scope
        }
        return setTagIfAbsent(
            JOB_KEY,
            CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
        )
    }

In Code C,您正在使用launch,这是CoroutineScope的扩展函数,根据源代码接受参数。

    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}
英文:

In Code A , You are creating you own coroutine using CoroutineScope Builder by giving Dispatcher so that's fine as it allows you to create it your own

In Code B , you are using viewModelScope which is extension property not (not accepting any arguments) coroutine builder like CoroutineScope or GlobalScope as you can see it's source code as mentioned below

public val ViewModel.viewModelScope: CoroutineScope
    get() {
        val scope: CoroutineScope? = this.getTag(JOB_KEY)
        if (scope != null) {
            return scope
        }
        return setTagIfAbsent(
            JOB_KEY,
            CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
        )
    }

In Code C , you are using launch which is extension function of CoroutineScope and accepting arguments as mentioned in source code

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

huangapple
  • 本文由 发表于 2023年5月11日 14:18:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76224667.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定