文章目录
GlobalScope 是一个特殊的 CoroutineScope,它是一个单例的 CoroutineScope,我们可以直接用它启动协程:
GlobalScope.launch {}
我们在 IDE 用 GlobalScope 时会有一条黄线,提示的是要小心使用它因为容易用错、容易写出问题:
当然我们理解了它的作用和适用场景后,是可以放心的使用它的。
前面讲解过的 CoroutineScope 调用 launch 启动的协程基本都会有内置的 Job,无论是自定义创建的 CoroutineScope,还是协程提供给我们的 CoroutineScope:
val scope = CoroutineScope(EmptyCoroutineContext) // 内部会创建一个 Job
val job = scope.launch {
coroutineContext[Job] // 这里一定会有 Job
}
我们简单看下 GlobalScope 的源码:
CoroutineScope.kt
@DelicateCoroutinesApi
public object GlobalScope : CoroutineScope {
// 重写了 coroutineContext,直接返回了 EmptyCoroutineContext
override val coroutineContext: CoroutineContext
get() = EmptyCoroutineContext
}
GlobalScope.launch {
// coroutineContext[Job] // 返回 null
// coroutineContext.job // 没有 job 抛出异常
}
可以看到 GlobalScope 重写了 coroutineContext,直接返回了 EmptyCoroutineContext。所以说 GlobalScope 真正的特点是它没有内置的 Job,因为 coroutineContext 就是一个空的上下文,自然也没有 Job。
没有 Job 的 CoroutineScope 有什么作用呢?没有 Job 说明它创建的协程就没有父协程,确切的说它创建的协程的 Job 就没有父 Job。
GlobalScope 的使用场景:在不需要和生命周期绑定又想启动协程的地方使用,因为没有父 Job 也就不会因任何组件的关闭而自动取消协程。CoroutineScope(EmptyCoroutineContext).launch 这么写又比较麻烦,所以提供了GlobalScope。使用它时做好及时关闭协程即可,并不是不能使用的东西。