Kotlin - 挂起函数(2)- 本质

73 阅读1分钟
本质

挂起函数为什么能被挂起恢复呢?难道靠suspend关键字描述函数就可以了?其实本质还是回调,只不过Kotlin编译器帮我们实现了而已。 将以下代码反编译看看

//定义挂起函数
suspend fun test() {
    val resultA = getA()
    val resultB = getB()
}

suspend fun getA(): String {
    //执行耗时任务
    return "A"
}

suspend fun getB(): String {
    //执行耗时任务
    return "B"
}

    
//将getA函数反编译看看
public final Object getA(@NotNull Continuation<String> $completion) {//2
    //执行耗时任务
    return "A";
}
  • 注释1:定义了挂起函数getName;
  • 注释2:反编译后看到,suspend关键字没有了,函数返回值为Object,增加入参Continuation $completion,泛型String为函数返回值;
Continuation是什么玩意?
public interface Continuation<in T> {//1
    /**
     * The context of the coroutine that corresponds to this continuation.
     */
    public val context: CoroutineContext//2

    /**
     * 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>)//3
}

  • 注释1:Continuation是一个接口,是不是有点回调的味道;
  • 注释2:维护协程上下文(Dispatchers、异常处理器等);
  • 注释3:回调接口,将结果回调到挂起点,然后执行后续的代码;
Java访问挂起函数
public void test(){
    new A().getA(new Continuation<String>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return null;
        }

        @Override
        public void resumeWith(@NonNull Object o) {

        }
    });
}

是不是又看到了回调的影子了。

那么具体协程是怎么实现挂起跟恢复的呢?有点复杂,有兴趣的可以关注下后续的分析。