请解释viewModelScope下三种协程写法的差异,验证个人理解是否正确
viewModelScope下三段协程代码的区别解析
我们逐个拆解这三段代码的核心差异,涵盖协程关系、执行逻辑、异常传播和生命周期绑定:
第一段:直接嵌套子协程
viewModelScope.launch { launch {} launch {} }
- 协程关系:两个内部
launch是外层协程的直接子协程,同属一棵协程树。 - 执行逻辑:两个子协程并行启动,外层协程执行完启动逻辑后即进入完成状态,但协程树会等待所有子协程结束才真正终止。
- 异常传播:正如你所说,任意一个子协程抛出未捕获异常时,会立即向上传播给父协程,父协程被取消的同时会终止所有其他子协程,最终整个协程树都会停止,异常由
viewModelScope的异常处理器处理。
第二段:启动viewModelScope的独立协程
viewModelScope.launch { viewModelScope.launch {} viewModelScope.launch {} }
- 协程关系:两个内部
viewModelScope.launch不是外层协程的子协程,而是直接绑定到viewModelScope的顶级子协程,和外层协程是同级关系。 - 执行逻辑:外层协程启动这两个独立协程后就自行结束,这两个协程彼此并行执行,生命周期完全独立于外层协程。
- 异常传播:由于
viewModelScope基于SupervisorJob,单个协程的未捕获异常只会取消自身,不会传播给其他同级协程,也不会影响外层协程的运行。 - 生命周期:这两个协程直接绑定ViewModel的生命周期,即使外层协程已经结束,它们仍会继续执行直到完成或ViewModel被销毁。
第三段:串行的结构化作用域
viewModelScope.launch { coroutineScope { launch {} } coroutineScope { launch {} } }
- 协程关系:每个
coroutineScope会创建新的结构化作用域,该作用域的Job是外层协程Job的子Job,内部的launch是对应coroutineScope的子协程。 - 执行逻辑:
coroutineScope会阻塞当前协程,直到其内部所有子协程完成才会继续执行后续代码。因此两个内部的launch是串行执行的——第一个coroutineScope内的协程完成后,才会启动第二个coroutineScope里的协程。 - 异常传播:如果某个
coroutineScope内的子协程抛出未捕获异常,会立即取消该作用域内的所有子协程,异常向上传播给外层协程,导致外层协程被取消,后续的coroutineScope不会被执行。 - 生命周期:所有内部协程都属于外层协程的协程树,ViewModel销毁时会被一并取消。
内容的提问来源于stack exchange,提问作者ethan
相关产品推荐
相关产品推荐

