Sou*_*a B 5 java kotlin kotlin-coroutines
Kotlin 协程是该语言的关键功能之一。我很好奇他们是如何实现的。所以我写了这个 kotlin 代码片段,
CoroutineScope(Dispatchers.IO).launch {
someFun(6) // A suspend fun with single int argument.
} // Which is converted into a synthetic method with an extra argument of continuation type added at the end.
Run Code Online (Sandbox Code Playgroud)
然后将其编译为字节码,然后将其反编译为Java(在Android Studio中)。我懂了,
BuildersKt.launch$default(CoroutineScopeKt.CoroutineScope((CoroutineContext)Dispatchers.getIO()), (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
private CoroutineScope p$;
Object L$0;
int label;
@Nullable
public final Object invokeSuspend(@NotNull Object $result) {
Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
CoroutineScope $this$launch;
switch(this.label) {
case 0:
ResultKt.throwOnFailure($result);
$this$launch = this.p$;
MainActivity var10000 = MainActivity.this;
this.L$0 = $this$launch;
this.label = 1;
if (var10000.someFun(6, this) == var3) {
return var3;
}
break;
case 1:
$this$launch = (CoroutineScope)this.L$0;
ResultKt.throwOnFailure($result);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
return Unit.INSTANCE;
}
@NotNull
public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
Intrinsics.checkNotNullParameter(completion, "completion");
Function2 var3 = new <anonymous constructor>(completion);
var3.p$ = (CoroutineScope)value;
return var3;
}
public final Object invoke(Object var1, Object var2) {
return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
}
}), 3, (Object)null);
Run Code Online (Sandbox Code Playgroud)
我理解了这段代码的某些部分。但仍有一些部分没有进入我的脑海。
根据这个答案,挂起函数在每个挂起点被分成多个延续,然后通过连续调用从头开始执行invokeSuspend。每次invokeSuspend调用when时,都会执行相应的switch case,然后更新lable. 所以下次调用时invokeSuspend,它会运行下一个案例。当 <it?> 被调用来挂起该函数时,它会停止调用invokeSuspend并等待恢复调用。一旦接到恢复电话,它就会再次正常继续。这就是我所知道的一切。
在第一行,Function2 构造函数接受 Continuation 的 null 对象。但为什么Function2类有一个单参数构造函数呢?我不知道Function2的实现。我搜索了它的源代码,但没有得到它。如果可能的话,我想要一个 .net 源代码的链接kotlin.jvm.functions.Function2。
case0: 的末尾,if (var10000.someFun(6, this) == var3) return var3;实际上意味着什么。
在先前对 invokeSuspend 的调用完成后,谁负责调用 invokeSuspend。它如何知道最后一个 invokeSuspend 案例何时执行?
3, (Object)null最后一个参数代表什么launch$default
让我尝试回答(我不是 Kotlin 专家,我从未在工作中使用过)。
\n\n\n我想要 kotlin.jvm.functions.Function2 源代码的链接。
\n
我在 Kotlin 的 JVM stdlib 实现中找到了它。
\n\npublic interface Function2<in P1, in P2, out R> : Function<R> {\n public operator fun invoke(p1: P1, p2: P2): R\n}\nRun Code Online (Sandbox Code Playgroud)\n我们使用它的原因可能是因为runBlocking需要suspend CoroutineScope.() -> T作为参数。CoroutineScope.()是 的扩展方法CoroutineScope,它是一个suspend函数,在与 Java 互操作时需要带有 2 个参数的函数。因此,CoroutineScope实例作为第一个参数传入,Continuation协程的延续实例作为第二个参数传入。
\n\ncase0: 的最后, if (var10000.someFun(6, this) == var3) return var3; 是什么意思?实际上意味着。
\n
我相信这是为了检查 是否someFun仍然暂停。\n如果它返回与(表明它已暂停)相同的值var3,那么当前函数也应该暂停并返回var3。
对此的一个很好的解释可以在The Beginner\xe2\x80\x99s Guide to Kotlin Coroutine Internals中找到。\n文章摘录:
\n\n\n我们可以看到挂起函数可以返回 IntrinsicsKt.getCOROUTINE_SUSPENDED() 或函数的实际结果。如果返回值是前一种情况,我们就知道我们正在调用的挂起函数还没有准备好,我们需要挂起当前函数并返回。
\n
回到你的问题。
\n\n\n在先前对 invokeSuspend 的调用完成后,谁负责调用 invokeSuspend。它如何知道最后一个 invokeSuspend 案例何时执行?
\n
我相信这将是 Kotlin 的协程调度程序。\n我没有具体证据,但通过嗅探 Kotlin 的源代码,我发现了这一点:
\n\n它似乎正在为该invokeSuspend方法构建一个函数对象,这让我认为它将在这一层中被调用,而不是从应用程序层生成的代码(即您的代码)。
\n\n3、(Object)null 在 launch$default 的最后一个参数中代表什么
\n
抱歉,我不太确定,因为我找不到 的源代码launch$default。\n如果我发现任何东西,请让我更新答案。
| 归档时间: |
|
| 查看次数: |
1522 次 |
| 最近记录: |