Kotlin:Coroutine的父母工作



我试图将以下功能迁移到Kotlin 1.3的新Coroutine

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()
    }
}

您的第二个示例是正确的。您可以使用plus将作业添加为新的Coroutine的父作业。

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 { ... }

您想要拥有的东西称为"结构化并发",通过将coroutines的生命周期与某些UI组件对齐。

儿童层次结构

您应该考虑实现自己的范围并维护Job,而不是使用GlobalScope,您也可以取消所有孩子。

这是一个简化的示例:

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 {
          //...
       }
    }
}

相关内容

  • 没有找到相关文章

最新更新