kotlin coroutines 协程教程(三)launch原理

原理篇(二)CoroutineScope.launch{} 过程分析

launch 的流程

先贴上 launch 的源码:

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
   
   
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}
step 1 创建 CoroutineContext

执行的代码块如下:

val newContext = newCoroutineContext(context)

首先会,根据传入的 CoroutineContext,由于没有传入 CoroutineContext,则使用默认的EmptyCoroutineContext,作为参数值

//CoroutineScope.newCoroutineContext() 方法
public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
   
   
    val combined = coroutineContext + context
    val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combined
    return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
        debug + Dispatchers.Default else debug
}

在这个 newCoroutineContext() 方法里面,会将作为参数的 Context,也就是 EmptyCoroutineContext,和当前的 Coroutine,也就是 BlockingCoroutine,关联在一起。

接着会根据是否 Debug 模式,如果是 Debug 的话,会对协程设置协程ID,方便调试;具体 Debug 设置,可以参考 Debug.kt 中 DEBUG_PROPERTY_NAME,相关解释。

最后根据当前的 CoroutineContext 是否有 Dispatcher,并且没有 ContinuationInterceptor,如果都没有的话,则为该 CoroutineContext 关联 Dispatchers.Default。由于我们是没有设置的,所以进入该方法,会给当前的 CoroutineContext 关联一个 Dispatchers.Default。

step 2 创建 Coroutine
 val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)

接着会根据 CoroutineStart 的模式,确认当前的 Coroutine 是 StandaloneCoroutine 还是 LazyStandaloneCoroutine。

至于两者的区别仅仅在于,Lazy 模式下:

  1. 构造参数 active = false,非 Lazy 默认是 true,这个值是传入作为 JobSupport 中作为构造函数,也是 Job 状态机里面的初始值变量,如下:

        private val _state = atomic<Any?>(if (active) EMPTY_ACTIVE else EMPTY_NEW)
    

    也就是说,如果是 Lazy 模式,则状态机进入的是 EMPTY_NEW 模式,非 Lazy 模式进入的是 EMPTY_ACTIVE 模式,这两个模式的可以简单认为,new 需要一种行为,让它进入 active。具体的解释,看Job-状态机 这一章节的分析

  2. Lazy 模式下,会将代码块存进 bolck 参数里面,等待调用 start(),join(),await() 等,会执行 onStart() 回调,这会,代码块才会真正的执行。

具体看源码如下:

//Builder.Common.kt 文件下
private open class StandaloneCoroutine(
    parentContext: CoroutineContext,
    active: Boolean
) : AbstractCoroutine<Unit>(parentContext, active) {
   
   
    override val cancelsParent: Boolean get() = true
    override fun handleJobException(exception: Throwable) = handleExceptionViaHandler(parentContext, exception)
}

private class LazyStandaloneCoroutine(
    parentContext: CoroutineContext,
    block: suspend CoroutineScope.() -> Unit
) : StandaloneCoroutine(parentContext, active = false) {
   
   
    private var block: (suspend CoroutineScope.() -> Unit)? = block

    override fun onStart(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值