Kotlin协程到底是怎么切换线程的?你是否知晓?

2.1.1 组合新的CoroutineContext

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

}

从上面可以提炼出以下信息:

1.会将launch方法传入的contextCoroutineScope中的context组合起来

2.如果combined中没有拦截器,会传入一个默认的拦截器,即Dispatchers.Default,这也解释了为什么我们没有传入拦截器时会有一个默认切换线程的效果

2.1.2 创建一个Continuation

val coroutine = if (start.isLazy)

LazyStandaloneCoroutine(newContext, block) else

StandaloneCoroutine(newContext, active = true)

coroutine.start(start, coroutine, block)

默认情况下,我们会创建一个StandloneCoroutine

值得注意的是,这个coroutine其实是我们协程体的complete,即成功后的回调,而不是协程体本身

然后调用coroutine.start,这表明协程开始启动了

2.2 协程的启动

public fun start(start: CoroutineStart, receiver: R, block: suspend R.() -> T) {

initParentJob()

start(block, receiver, this)

}

接着调用CoroutineStartstart来启动协程,默认情况下调用的是CoroutineStart.Default

经过层层调用,最后到达了:

internal fun <R, T> (suspend ® -> T).startCoroutineCancellable(receiver: R, completion: Continuation) =

runSafely(completion) {

// 外面再包一层 Coroutine

createCoroutineUnintercepted(receiver, completion)

// 如果需要,做拦截处理

.intercepted()

// 调用 resumeWith 方法

.resumeCancellableWith(Result.success(Unit))

}

这里就是协程启动的核心代码,虽然比较短,却包括3个步骤:

1.创建协程体Continuation

2.创建拦截 Continuation,即DispatchedContinuation

3.执行DispatchedContinuation.resumeWith方法

2.3 创建协程体Continuation

调用createCoroutineUnintercepted,会把我们的协程体即suspend block转换成Continuation,它是SuspendLambda,继承自ContinuationImpl

createCoroutineUnintercepted方法在源码中找不到具体实现,不过如果你把协程体代码反编译后就可以看到真正的实现

详情可见:字节码反编译

2.4 创建DispatchedContinuation

public actual fun Cont

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值