接着调用CoroutineStart
的start
来启动协程,默认情况下调用的是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 Continuation.intercepted(): Continuation =
(this as? ContinuationImpl)?.intercepted() ?: this
//ContinuationImpl
public fun intercepted(): Continuation<Any?> =
intercepted
?: (context[ContinuationInterceptor]?.interceptContinuation(this) ?: this)
.also { intercepted = it }
//CoroutineDispatcher
public final override fun interceptContinuation(continuation: Continuation): Continuation =
DispatchedContinuation(this, continuation)
从上可以提炼出以下信息
1.interepted
是个扩展方法,最后会调用到ContinuationImpl.intercepted
方法
2.在intercepted
会利用CoroutineContext
,获取当前的拦截器
3.因为当前的拦截器是CoroutineDispatcher
,因此最终会返回一个DispatchedContinuation
,我们其实也是利用它实现线程切换的
4.我们将协程体的Continuation
传入DispatchedContinuation
,这里其实用到了装饰器模式
,实现功能的增强