Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 为什么必须;调度员。主“调度员”;是否添加到Activitys CoroutineScope实现的根作业?_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android 为什么必须;调度员。主“调度员”;是否添加到Activitys CoroutineScope实现的根作业?

Android 为什么必须;调度员。主“调度员”;是否添加到Activitys CoroutineScope实现的根作业?,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,此示例复制自,并由launch(Dispatchers.Main)coroutine扩展。我不明白为什么第4行需要+调度员.Main。如果我删除此部分,则如果活动被销毁,launchcoroutine将被取消。那么,Dispatchers.Main的原因是什么呢?为什么没有添加Dispatchers.IO呢?由于Kotlin 1.3,您需要一个CoroutineScope来启动一个新的coroutine。 在您的示例中,您将活动的范围创建为val: abstract class ScopedAp

此示例复制自,并由
launch(Dispatchers.Main)
coroutine扩展。我不明白为什么第4行需要
+调度员.Main
。如果我删除此部分,则如果活动被销毁,
launch
coroutine将被取消。那么,Dispatchers.Main的原因是什么呢?为什么没有添加
Dispatchers.IO
呢?

由于Kotlin 1.3,您需要一个
CoroutineScope
来启动一个新的coroutine。 在您的示例中,您将活动的范围创建为
val

abstract class ScopedAppActivity: AppCompatActivity(), CoroutineScope {
    protected lateinit var job: Job
    override val coroutineContext: CoroutineContext 
        get() = job + Dispatchers.Main

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        job = Job()

        launch(Dispatchers.Main) {
            try {
                delay(Long.MAX_VALUE)
            } catch (e: Exception) {
                // e will be a JobCancellationException if the activty is destroyed
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    } 
}
协同路由范围由不同的部分组成,例如调度器和作业。 dispatcher用于启动协同路由-选择线程-作业用作从此作用域创建的协同路由的父级

如果在调用
launch
方法时指定另一个调度程序,此调度程序将覆盖标准调度程序:

override val coroutineContext: CoroutineContext 
    get() = job + Dispatchers.Main
在您的示例中,给定的
Dispatchers.Main
覆盖了标准的
Dispatchers.Main
——什么都不会发生


通常,您要定义一个标准的调度器,该调度器在您的活动的大多数地方都使用,并且仅在需要时指定一个特殊的调度器。

首先,我不是常规的专家:

第一个问题:我不明白为什么需要+调度员。主线4。如果我删除此部分,则如果活动被销毁,则启动协同程序将被取消。那么,派遣人员的原因是什么呢

你有一个作业活动生命周期调度程序关联。MainAndroid主线程调度程序关联,并与UI对象操作

看起来很整洁。如果您的活动正在破坏,您将取消您的作业,如果您的主线程结束(例如发生异常),您将取消您的作业

第二个问题:为什么不添加Dispatchers.IO

在本例中,更改为应用程序主线程上的另一个线程是没有意义的,因为编写以下内容时,活动位于主线程中:

launch(Dispatchers.Main) 
您可能没有意识到,
launch
实际上是以您的
scopedappacitivity
作为接收器调用的。所以你写得很好

launch(Dispatchers.Main) {
    try {
        delay(Long.MAX_VALUE)
    } catch (e: Exception) {
        // e will be a JobCancellationException if the activty is destroyed
    }
}
launch
CoroutineScope
上的一个扩展函数,它将使用其
coroutineContext
作为起点,并将其与括号中指定的内容相结合。因此,在你的例子中,有效的上下文是

this.launch(Dispatchers.Main) { ... }
你可以想象,这等于

job + Dispatchers.Main + Dispatchers.Main
因此,当您从
coroutineContext
中删除
Dispatchers.Main
时,没有任何变化

那么,派遣人员的原因是什么呢

coroutineContext
中提供
Dispatchers.Main
的优点是,您不必每次都提供它,因此只需编写

job + Dispatchers.Main
launch
中的块将保留在GUI线程上,这是在Android和其他GUI应用程序上使用协同程序的最自然的方式

为什么不添加Dispatchers.IO

因为这一行不是关于声明您将使用的所有Dispatcher,而是默认Dispatcher,所以提供多个Dispatcher是没有意义的


在另一个层次上,
CoroutineContext
不是一个列表(由
+
操作符暗示),而是一个映射。
+
语法之所以有效,是因为您添加的每个对象都声明了自己的映射键,
+
使用该键将其放入上下文的内部映射中。因此,实际上不可能将两个Dispatcher放入一个
CoroutineContext

中,然后可以删除受保护的lateinit var job:job并简单地替换为
覆盖val CoroutineContext:CoroutineContext=job()+Dispatchers.Main
,并在
onDestroy
中进一步替换为
coroutineContext.cancel()
?是的,我相信这会起作用。它唯一改变的是
Job()
在调用
onCreate()
之前就已经存在,因此您可以在活动到达
create
生命周期点之前启动一个协同程序。我认为这更多的是理论上的差异,而不是实践上的差异。
launch { ... }