为了活动小家电-GlobalScope使用(二)

68 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的11天,点击查看活动详情

为了活动小家电,接着上篇搞!

这次的结束处理怎么样?

错误可以如上处理,但是这次退出呢?

它是大致可以预测的,但由于它不是遵循生命周期的,因此终止不会丢失。

即使屏幕关闭,这个协程也不会因延迟而终止,但根据情况可能会发生错误。

  • 如果一个 Activity 或 Fragment 立即终止并且视图被炸毁,则可能会发生错误。

单独创建一个作业,并将该作业附加到您正在使用的 GlobalScope 的启动中。

private val job = SupervisorJob()

fun loadGlobal() = GlobalScope.launch(exception + job) {
    GlobalScope.launch(job) {
        ...
    }
    delay(5000)
    launch(Dispatchers.Main) {
        ...
    }
}

override fun onDestory() {
    super.onDestory()
    job.cancel()
}

事实上,以这种方式工作是没有问题的。

虽然不安全。

是的,这不安全 确认除非应用取消,否则 GlobalScope 会持续运行。最后,它应该直接应用于要使用的代码的启动,而不是 GlobalScope 本身。

如果有人在启动时不小心不处理作业和异常,当然会有问题。

// viewmodel源码
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))
        }

internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context

    override fun close() {
        coroutineContext.cancel()
    }
}

总结

  • GlobalScope 是一个根据应用程序生命周期运行的单例。
  • 过度使用 GlobalScope 可能会导致应用程序行为出现问题。
  • GlobalScope 取消起来很复杂。
  • GlobalScope 对抛出异常的处理也很复杂。

复杂性意味着你可以省略它。能够省略意味着如果你不知道和编写你正在编写的代码,你总是会遇到可能出现的问题。

最后,我建议不要使用它。 当然,在Android中,要是用它最好实现它遵循生命周期并设计它,使之不存在内存问题。

如果你看一下 runBlocking,一个使用一些 GlobalScope 的代码,一个新的上下文被创建并与 GlobalScope.newCoroutineContext(context + eventLoop) 一起使用。至少这意味着注入一个新的上下文。 你可能会说你可以像这部分一样使用 GlobalScope 而不是 CoroutineScope,但这是你的选择。 推荐 CoroutineScope 的原因有据可查,使用它进行开发是最基本的。