破解Kotlin协程创建调用的那些事

Kotlin协程从1.3正式版除出来也很久了,相比大家伙也比较熟悉了,从Android的AAC架构到后后端都可以见到它的身影,那么问题来了,用了那么久的协程体你知道它怎么创建的么。

一天我问同事:你知不知道协程是怎么创建的?

同事:我知道,是launchasync...

我:?????

我:那如果抛开官方给的框架,就用Kotlin语言提供的最基本的API创建呢?

同事:????,那你创个毛。

此时人送外号逼王的我,知道机会来了。于是乎就有了这个文章。

预备知识

首先,你需要知道协程是啥玩意,知道基本概念之后在来看(知道的话,当我没有说

好戏开场了

我们抛开官方的框架,只用语言最基本的API来洞悉Kotlin协程的内部设计。

为了接下来方便带领大家分析,我把用到的概念和API给贴出来,方便分析。

一般启动协程我们需要:

1、一个suspend fun

suspend fun foo() {}
复制代码

2、一个启动协程的API:startCoroutine,如果不想要立即执行,则可用:createCoroutine

@SinceKotlin("1.3")
@Suppress("UNCHECKED_CAST")
public fun <T> (suspend () -> T).startCoroutine(
    completion: Continuation<T>
) {
    createCoroutineUnintercepted(completion).intercepted().resume(Unit)
}
复制代码
@SinceKotlin("1.3")
@Suppress("UNCHECKED_CAST")
public fun <T> (suspend () -> T).createCoroutine(
    completion: Continuation<T>
): Continuation<Unit> =
    SafeContinuation(createCoroutineUnintercepted(completion).intercepted(), COROUTINE_SUSPENDED)

复制代码

上面创建协程和启动协程中我们看到有一个非常关键的方法:createCoroutineUnintercepted方法实现如下(具体功能稍后在说:

@SinceKotlin("1.3")
public actual fun <T> (suspend () -> T).createCoroutineUnintercepted(
    completion: Continuation<T>
): Continuation<Unit> {
    val probeCompletion = probeCoroutineCreated(completion)
    return if (this is BaseContinuationImpl)
        create(probeCompletion)
    else
        createCoroutineFromSuspendFunction(probeCompletion) {
            (this as Function1<Continuation<T>, Any?>).invoke(it)
        }
}
复制代码

3、协程执行完后需要一个 completion 来回调,即: Continuation

@SinceKotlin("1.3")
public interface Continuation<in T> {
    /**
     * The context of the coroutine that corresponds to this continuation.
     */
    public val context: CoroutineContext

    /**
     * Resumes the execution of the corresponding coroutine passing a successful or failed [result] as the
     * return value of the last suspension point.
     */
    public fun resumeWith(result: Result<T>)
}
复制代码

4、BaseContinuationImpl

@SinceKotlin("1.3")
internal abstract class BaseContinuationImpl(
    // This is `public val` so that it is private on JVM and cannot be modified by untrusted code, yet
    // it has a public getter (since even untrusted code is allowed to inspect its call stack).
    public val completion: Continuation<Any?>?
) : Continuation<Any?>, CoroutineStackFrame, Serializable {
    // This implementation is final. This fact is used to unroll resumeWith recursion.
    public final override fun resumeWith(result: Result<Any?>) {
        // This loop unrolls recursion in current.resumeWith(param) to make saner and shorter stack traces on resume
        var current = this
        var param = result
        while (true) {
            // Invoke "resume" debug probe on every resumed continuation, so that a debugging library infrastructure
            // can precisely track what part of suspended callstack was already resumed
            probeCoroutin
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值