携手创作,共同成长!这是我参与「掘金日新计划 · 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 的原因有据可查,使用它进行开发是最基本的。