Android Kotlin lifecycleScope协程执行顺序差异原因咨询
协程执行顺序差异核心原因
首先明确两个基础规则:
lifecycleScope默认使用Dispatchers.Main.immediate调度器,该调度器的核心逻辑是:仅当主线程空闲、没有正在执行的协程调度批次时,新提交的协程任务才会在当前线程立即执行;如果当前正处于一段协程代码的执行流程中(还没碰到挂起点、代码没执行完),新提交的协程任务会进入主线程队列排队,不会打断当前正在运行的代码。- 协程的
launch启动默认使用CoroutineStart.DEFAULT模式,提交子协程任务后不会阻塞当前协程的后续执行,子协程具体什么时候跑完全由调度器决定。
test2输出1、3、2的执行流程
test2代码如下:
private fun test2() { lifecycleScope.launch { Log.d("Test", "1") launch { Log.d("Test", "2") } Log.d("Test", "3") }// print 1, 3, 2 }
执行步骤拆解:
lifecycleScope.launch将外层协程块提交到主线程队列排队,等主线程空闲时启动执行- 外层协程拿到执行权,首先打印
1 - 执行内层
launch提交打印2的子协程任务:此时外层协程从启动开始还没有遇到任何挂起点,正处于调度器的执行批次中,因此子协程任务不会立即执行,会被追加到主线程任务队列末尾排队 - 内层任务提交完成后,外层协程没有挂起点,继续向下执行打印
3 - 外层协程这段无挂起的代码全部执行完,当前调度批次结束,主线程取出排队的子协程任务执行,打印
2
这个结果是固定调度逻辑,不是运行时的随机现象。
test1输出1、2、3的核心差异
test1代码如下:
private fun test1() { lifecycleScope.launch { Log.d("Test", "1") delay(1000) launch { Log.d("Test", "2") } Log.d("Test", "3") }// print 1, 2, 3 }
和test2的唯一区别是多了delay(1000)挂起函数,执行流程差异点就在这里:
- 外层协程启动后先打印
1,随后执行delay(1000):这是挂起函数,会立即让出主线程执行权,当前的调度批次直接结束,外层协程暂时挂起,主线程可以处理其他队列任务 - 1秒延迟时间到,外层协程被重新调度恢复执行,此时调度器会重置执行批次标记——当前没有正在运行的未完成协程代码块
- 执行内层
launch提交打印2的子协程任务:因为当前主线程处于空闲调度状态,符合Main.immediate的立即执行条件,子协程任务不会排队,直接执行打印2 - 子协程执行完成后,回到外层协程继续向下执行,打印
3
因此最终输出顺序是1、2、3。
补充验证:如果给test2的内层launch加上CoroutineStart.UNDISPATCHED参数,强制子协程在当前上下文立即执行、忽略调度器排队规则,输出顺序也会变成1、2、3。
内容的提问来源于stack exchange,提问作者Đào Mạnh Tuấn
相关产品推荐
相关产品推荐

