我正在尝试将以下功能迁移到Coroutine
中的新Kotlin 1.3
:
fun launchUI(strategy: CancelStrategy, block: suspend CoroutineScope.() -> Unit): Job {
return launch(context = UI, parent = strategy.jobs, block = block)
}
但是新的GlobalScope.launch
函数没有parent
参数。文档说:
父作业也从
CoroutineScope
继承,但是它 也可以用相应的coroutineContext
元素覆盖。
但是我不知道该如何替代父级工作。我现在已经像这样实现了,但是我不确定它是否可以相同的方式工作:
fun launchUI(strategy: CancelStrategy, block: suspend CoroutineScope.() -> Unit): Job {
val job = GlobalScope.launch(context = Dispatchers.Main, block = block)
strategy.jobs.invokeOnCompletion {
job.cancel()
}
return job
}
有人可以帮助我吗?
更新:
class CancelStrategy(owner: LifecycleOwner, val jobs: Job) : LifecycleObserver {
init {
owner.lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
jobs.cancel()
}
}
答案 0 :(得分:0)
您的第二个示例是正确的。您可以使用plus
将作业添加为新协程的父作业。
fun launchUI(strategy: CancelStrategy, block: suspend CoroutineScope.() -> Unit): Job {
return GlobalScope.launch(context = Dispatchers.Main + strategy.jobs, block = block)
}
但是不鼓励使用GlobalScope
。最好创建自己的CoroutineScope
。您的CancelStrategy
看起来不错。
class CancelStrategy(owner: LifecycleOwner, val jobs: Job) : LifecycleObserver, CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + jobs
init {
owner.lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
jobs.cancel()
}
}
现在,您可以像这样启动协程了:
cancelStrategy.launch { ... }
答案 1 :(得分:0)
通过将协程的生命周期与某个UI组件对齐,可以将其称为“结构化并发”。
您应该考虑实现自己的作用域并维护一个GlobalScope
,而不是使用Job
,也可以取消该作用域以取消所有孩子。
这是一个简化的示例:
class Activity : CoroutineScope {
lateinit var job: Job //tied to lifecycle of Activity
fun create() {
job = Job()
}
fun destroy() {
//will cancel all child jobs as well
println("cancel $job and all ${job.children.toList().size} children")
job.cancel()
}
override val coroutineContext: CoroutineContext
get() = Dispatchers.Default + job + CoroutineName("MyActivityContext")
fun doSomething() {
//we launch in the outer scope of Activity
launch {
//...
}
}
}