我们知道协程体会被Kotlin编译器转换为以下代码
static final class LaunchUnderTheHoodKt$testLaunch$1 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Unit>, Object> {
int label;
LaunchUnderTheHoodKt$testLaunch$1(Continuation $completion) {
super(2, $completion);
}
@Nullable
@Override
public final Object invokeSuspend(@NotNull Object $result) {
@Override
public final Object invoke(@NotNull CoroutineScope p1, @Nullable Continuation p2) {}
@NonNull
@Override
public final Continuation create(@Nullable Object value, @NotNull Continuation $completion) {}
}
}
分析重点
我们知道LaunchUnderTheHoodKt1表示协程体。那么创建了LaunchUnderTheHoodKt1对象,也就是协程被创建了,所以只要关注底层如何触发create函数这个重点就可以了,有这个前提才就不至于在源码中迷失。
到GlobalScope.launch一探究竟
- GlobalScope.launch 扩展函数启动协程
public fun CoroutineScope.launch(//1
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)//2
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)//3
coroutine.start(start, coroutine, block)//4
return coroutine//5
}
- 注释1:launch是CoroutineScope的扩展函数,EmptyCoroutineContext表示空上下,那么协程就是Dispatchers.Default线程池上执行;CoroutineStart表示启动方式,CoroutineStart.DEFAULT表示立即启动,block表示协程体,也就是LaunchUnderTheHoodKt1对象;
- 注释2:子协程继承父协程的上下文(例如Dispatchers),返回一个新的上下文;
- 注释3:因为不是lazy启动,所以返回StandaloneCoroutine;
- 注释4:传入启动模式、StandaloneCoroutine对象、协程体,开始启动协程;
- 注释5:返回coroutine,其实是Job,具备控制协程的能力,例如取消协程;
- StandaloneCoroutine的父类是AbstractCoroutine,所以AbstractCoroutine.start启动协程
public abstract class AbstractCoroutine<in T>(
parentContext: CoroutineContext,
initParentJob: Boolean,
active: Boolean
) : JobSupport(active), Job, Continuation<T>, CoroutineScope {
//省略部分代码
public fun <R> start(start: CoroutineStart, receiver: R, block: suspend R.() -> T) {
start(block, receiver, this)//1
}
//CoroutineStart类中
public enum class CoroutineStart {
......
@InternalCoroutinesApi
public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>): Unit =
when (this) {
DEFAULT -> block.startCoroutineCancellable(completion)//2
ATOMIC -> block.startCoroutine(completion)
UNDISPATCHED -> block.startCoroutineUndispatched(completion)
LAZY -> Unit // will start lazily
}
- 注释1:触发CoroutineStart的invoke函数,有点意思吧,我当时还找半天,到底跳转哪里去了;
- 注释2:前面我们知道,start的类型是DEFAULT,所以触发block.startCoroutineCancellable(completion);
- startCoroutineCancellable 负责创建协程、封装协程、启动协程
public fun <T> (suspend () -> T).startCoroutineCancellable(completion: Continuation<T>): Unit = runSafely(completion) {
createCoroutineUnintercepted(completion).intercepted().resumeCancellableWith(Result.success(Unit))//1
}
- 注释1:startCoroutineCancellable是扩展函数,任何协程体都可以调用,这里有三个动作,createCoroutineUnintercepted创建协程,intercepted负责封装协程,resumeCancellableWith启动协程;
- createCoroutineUnintercepted创建协程
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
completion: Continuation<T>
): Continuation<Unit> {//1
val probeCompletion = probeCoroutineCreated(completion)
return if (this is BaseContinuationImpl)
create(probeCompletion)//2
else
createCoroutineFromSuspendFunction(probeCompletion) {
(this as Function1<Continuation<T>, Any?>).invoke(it)
}
}
- 注释1:actual表示这是对createCoroutineUnintercepted的实现,不同平台有不同的实现,这是Java平台的实现;
- 注释2:前面一直通过block的扩展函数来调用,所以这里的this就是协程体block,也就是LaunchUnderTheHoodKt1,间接继承BaseContinuationImpl),所以会触发if分支的create,重点来了,create在LaunchUnderTheHoodKt1被重写了;
- LaunchUnderTheHoodKt1.create创建协程对象
static final class LaunchUnderTheHoodKt$testLaunch$1 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Unit>, Object> {
......
@NonNull
@Override
public final Continuation create(@Nullable Object value, @NotNull Continuation $completion) {
return (Continuation) new LaunchUnderTheHoodKt$testLaunch$1($completion);//1
}
}
这里主要分析协程体的创建流程,关于如何启动,可以关注juejin.cn/editor/draf…
总结
协程的创建也就是LaunchUnderTheHoodKt1对象的创建;
以上分析有不对的地方,请指出,互相学习,谢谢哦!