先上一张流程图
![](https://img-blog.csdnimg.cn/img_convert/806e1e905d8c1a44623b66173644c28c.png)
追踪源码前,先了解一些Kotlin高阶写法,方便阅读代码
高阶拓展函数 T.()
一种类似 (T) 效果的写法
class A() {
fun testA(block: A.() -> Unit) {
block(this)
}
}
val a = A()
a.testA {
this // 指的就是a
}
operator关键字
(1) 重写 []
class A(){
operator fun get(i:Int):String {
when(i){
1->"a"
else ->""
}
}
}
val a = A()
val value = a[1]
(2) 重写 +
class A(){
operator fun plus(a:A):A{
}
}
val value = A() + A() // 这个写法就是CoroutineContext的基础实现方法
invoke的写法
class A(){
fun invoke(i:Int)
}
val a = A()
a.invoke(1)
a(1) // invoke可以省略
kotlin的扩展方法编译成java时,会生成一个类,构造方法的参数就是 该类 加 扩展方法的参数
通过最简单的协程调用方法来追踪协程的源码执行流程
suspend fun testA() {
}
// 最简单的调用
GlobalScope.launch {
testA()
}
拓展方法launch编译后被替换成
![](https://img-blog.csdnimg.cn/img_convert/1da54174916317bd33b43c9a10e74eb8.png)
在BuildersKt和BuildersKt_Builders_commonKt 两个类之间相互调用
![](https://img-blog.csdnimg.cn/img_convert/61c10ddf3ccab97dbf025cec265a3df4.png)
![](https://img-blog.csdnimg.cn/img_convert/af3faa6d12d5bf16bf8a44f6333625ff.png)
生成StandaloneCoroutine类,这个类的基类在注解说明了该类的作用:
协程构建器中协程实现的抽象基类。此类实现完成 Continuation、Job 和 CoroutineScope 接口。 它将继续的结果存储在作业的状态中。 此协程在完成之前等待子协程完成,并通过中间失败状态失败。
调用start方法,通过CoroutineStart创建Continuation(这个类实现挂起和取消挂起的关键作用)
![](https://img-blog.csdnimg.cn/img_convert/f49a3c74075a7f073b809b75b074af74.png)
调用CoroutineStart的invoke方法
![](https://img-blog.csdnimg.cn/img_convert/7c374fa7b28ab0db67887e5b517fffc6.png)
![](https://img-blog.csdnimg.cn/img_convert/ecbb4e6a2e87b4e70432993e95182dbc.png)
图中有三个拓展函数,下面将分成三个点
补充:Continuation这个类,代表的就是一个状态机
![](https://img-blog.csdnimg.cn/img_convert/3a22272f97f5a09660ad81c8704701ba.png)
基类唯一一个变量CoroutineContext,是一个链表,存在当前协程的所有状态;resumeWith,注解写的意思就是 恢复执行相应的协程,将成功或失败的结果作为最后一个暂停点的返回值。当调用一个suspend方法时,当前方法的协议就在该位置被挂起,等suspend方法内的代码被执行完后,调用resumeWith回调被挂起的位置取消挂起继续执行,就结果作为参数返回,具体代码如下
![](https://img-blog.csdnimg.cn/img_convert/61b7226c29d3da932fc97ff6d817ddd1.png)
![](https://img-blog.csdnimg.cn/img_convert/adb8cc4e6408b04beec589e07dc6efd2.png)
这里地方应该就是协程能够实现挂起,切换线程等待的巧妙之处,本质还是使用了callback的做法
调用CoroutineStart的invoke方法创建Continuation,调用Funtion2的扩展方方法startCoroutineCancellable,创建继承ContinuationImpl的实例
![](https://img-blog.csdnimg.cn/img_convert/432c8aff4236c5849a7cbed309567ef3.png)
调用了ContinuationImpl的intercepter方法
![](https://img-blog.csdnimg.cn/img_convert/8d848cd0aab1f6ef3f873c99774d35c5.png)
![](https://img-blog.csdnimg.cn/img_convert/9b2c753802056da3a6a066699ed2a762.png)
context[ContinuationInterceptor] 返回是一个 CoroutineDispatcher,调用intercepetContinuation 返回 继承DispatchedTask 本质也是一个runnable
调用resumeCancellableWith 将任务塞到Dispatcher(这里实现线程切换)
![](https://img-blog.csdnimg.cn/img_convert/f55a6ceae5ece302339eeea40b04d55e.png)
由于我们一开始是lauch(CoroutineStart.DEFAULT)
![](https://img-blog.csdnimg.cn/img_convert/f23114e60a5bc53d0c09d66fbf7e4c37.png)
![](https://img-blog.csdnimg.cn/img_convert/1c5b1fcdfd78c45141a7a370564fc4dd.png)
调用Dispatchers.Default的dispathch方法,会进入到对应的线程池内,等待执行
![](https://img-blog.csdnimg.cn/img_convert/b96b55d23fbf16593f99076410a932d6.png)
被执行
![](https://img-blog.csdnimg.cn/img_convert/adbf657883b4d8e8dfc765a873e71c7c.png)
runSafely方法内执行的是之前CoroutineDispatcher的run方法
![](https://img-blog.csdnimg.cn/img_convert/6af299698b15ea22852f047af35473fa.png)
开始执行我们的目标的业务代码
![](https://img-blog.csdnimg.cn/img_convert/a1e423073db56debfe632b696d73fe7a.png)
进而调用ContinuationImpl的resumeWith 进而调用最开始的invokeSuspend
![](https://img-blog.csdnimg.cn/img_convert/8b0721388a54fba011b10971a8a1bd88.png)
通过Continuation这个状态机进而suspend方法的调用,当前方法的挂起和取消挂起
![](https://img-blog.csdnimg.cn/img_convert/f2410a44bb5ca5c5f3113a2d11c5bc08.png)
到这里就是一次完整的最简单的协程调用。当我们再协程里面继续通过关键字withContext,开启新的协程,其实本质就是再嵌套了一层上面的调用流程,唯一的不用就是不用再新建一个新的Continuation,而是把当前协程的Continuation继续往下传递,从而实现父协程可以控制子协程,并且子协程可以挂起父协程或取消挂起
![](https://img-blog.csdnimg.cn/img_convert/2190789c8eb203d91ebc449880d6708b.png)