CoroutineScope(SupervisorJob())与全局作用域的区别

3
这两者有什么区别?
我在跟随教程时,老师说我们需要一个随着应用程序一起存在的作用域,用SupervisorJob手动创建作用域。但是GlobalScope不是也可以做同样的事情吗?
我研究了一下,但找不到合适的解释。谢谢。

1
这个回答解决了你的问题吗?https://dev59.com/yVEG5IYBdhLWcg3wgPt3 - Darshan
@DarShan 不,与SupervisorJob()无关。 - jane
SupervisorJob 的作用是,如果其中一个 子协程 失败,其他协程不会受到影响。如果没有 SupervisorJob,则如果一个子协程失败,则所有协程都将被终止。 - Darshan
@DarShan,这在GlobalScope中不是这种情况吗? - jane
1个回答

1
这两个示例的区别在于GlobalScope无法取消,而另一个可以。当您在使用CoroutineScope()构造函数创建的CoroutineScope上调用cancel()时,它的所有子协程都将被取消。
如果您尝试在GlobalScope上调用cancel(),它将抛出IllegalStateException异常,因为它没有Job来作为其启动的协程的父级。
当您调用CoroutineScope()而不传递Job时,它会自动获取一个通用Job作为其协程的父级。像这样的通用父Job将取消其所有子协程,如果其中任何一个失败。如果您明确使用SupervisorJob(),则如果其中任何一个子项失败,则不会导致取消所有兄弟协程。这是一种类似于GlobalScope的行为,因为GlobalScope协程没有兄弟姐妹,它们可以通过共享的父级导致被取消。
GlobalScope不建议使用的原因是它没有监督功能。它只应用于整个应用程序会话的生命周期内运行的协程。但是,如果您正在进行不应在Android上取消的重要工作,则协程也不是一个好选择,因为它们未处理应用程序处于后台的情况。在这些情况下,您应该使用服务或WorkManager。因此,对于GlobalScope或任何永远不会被取消的CoroutineScope的实际合法用例非常罕见。
我认为添加@DelicateCoroutinesApi的原因是许多人误用了GlobalScope。(可能是因为他们在如何使用协程的初学者文档中不幸地使用了它。)使用CoroutineScope(SupervisorJob())CoroutineScope(Dispatchers.IO)等而不是GlobalScope来绕过警告是不正确的,因为这只是掩盖了警告,而不改变行为,除了创建一个多余的CoroutineScope。如果您有一个合法的GlobalScope用例,请使用@OptIn(DelicateCoroutinesApi::class)来消除警告。

除了无法取消之外,如果我想要一个与应用程序一样长寿的作用域,有什么理由不使用GlobalScope呢? - jane
1
我添加了一个解释段落。协程不能很好地处理您应用程序的后台状态。如果您只是定期记录某些内容,那么可以使用它。如果您正在执行一些关键操作,例如在保存大型视频文件之前进行处理,则协程根本不适合使用,无论是否使用GlobalScope。 - Tenfour04
我现在明白了。谢谢你的时间! - jane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接