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。如果我删除此部分,则如果活动被销毁,则启动协同程序将被取消。那么,派遣人员的原因是什么呢 你有一个作业与活动生命周期和调度程序关联。Main与Android主线程调度程序关联,并与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 { ... }