Kotlin Coroutine Suspend的魔法🪄揭秘(附文) —— Show me code

432 阅读2分钟

Suspend代码

class SuspendFunctionExploring {

    suspend fun loadData() {
        val data = networkRequest()
        show(data)
    }

    suspend fun networkRequest(): Data = withContext(Dispatchers.IO) {
        return@withContext Data()
    }


    fun show(data: Data) {

    }

}

反编译后代码

// SuspendFunctionExploring.java
@Metadata(
   mv = {1, 4, 3},
   bv = {1, 0, 3},
   k = 1,
   d1 = {"\u0000\u001c\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0002\b\u0003\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u0011\u0010\u0003\u001a\u00020\u0004H\u0086@ø\u0001\u0000¢\u0006\u0002\u0010\u0005J\u0011\u0010\u0006\u001a\u00020\u0007H\u0086@ø\u0001\u0000¢\u0006\u0002\u0010\u0005J\u000e\u0010\b\u001a\u00020\u00042\u0006\u0010\t\u001a\u00020\u0007\u0082\u0002\u0004\n\u0002\b\u0019¨\u0006\n"},
   d2 = {"Lcom/magellan/i18n/order/forward_order/center/middleware/model/SuspendFunctionExploring;", "", "()V", "loadData", "", "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", "networkRequest", "Lcom/magellan/i18n/order/forward_order/center/middleware/model/Data;", "show", "data", "business_order_impl"}
)
public final class SuspendFunctionExploring {
   @Nullable
   public final Object loadData(@NotNull Continuation var1) {
      Object $continuation;
      label20: {
         if (var1 instanceof <undefinedtype>) {
            $continuation = (<undefinedtype>)var1;
            if ((((<undefinedtype>)$continuation).label & Integer.MIN_VALUE) != 0) {
               ((<undefinedtype>)$continuation).label -= Integer.MIN_VALUE;
               break label20;
            }
         }
         
         //当前方法的continueation(callback),会传给下层suspend方法,以便回调.
         $continuation = new ContinuationImpl(var1) {
            // $FF: synthetic field
            Object result;
            int label;
            Object L$0;

            @Nullable
            //当前方法的suspend回调处
            public final Object invokeSuspend(@NotNull Object $result) {
               this.result = $result;
               this.label |= Integer.MIN_VALUE;
               return SuspendFunctionExploring.this.loadData(this);
            }
         };
      }

      Object $result = ((<undefinedtype>)$continuation).result;
      Object var5 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      Object var10000;
      
      //核心:
      //有限状态机的实现,使得该方法可以被分成两个阶段. 
      //一个suspend 即把该方法分成两个阶段,两个suspend就三个阶段.
      switch(((<undefinedtype>)$continuation).label) {
          case 0:
             ResultKt.throwOnFailure($result);
             ((<undefinedtype>)$continuation).L$0 = this;
             ((<undefinedtype>)$continuation).label = 1;
             var10000 = this.networkRequest((Continuation)$continuation);
             if (var10000 == var5) {
                return var5;
             }
             break;
          case 1:
             this = (SuspendFunctionExploring)((<undefinedtype>)$continuation).L$0;
             ResultKt.throwOnFailure($result);
             var10000 = $result;
             break;
          default:
             throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }

      Data data = (Data)var10000;
      this.show(data);
      return Unit.INSTANCE;
   }

   @Nullable
   public final Object networkRequest(@NotNull Continuation $completion) {
      return BuildersKt.withContext((CoroutineContext)Dispatchers.getIO(), (Function2)(new Function2((Continuation)null) {
         int label;

         @Nullable
         public final Object invokeSuspend(@NotNull Object var1) {
            Object var2 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
            switch(this.label) {
            case 0:
               ResultKt.throwOnFailure(var1);
               return new Data();
            default:
               throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
            }
         }

         @NotNull
         public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
            Intrinsics.checkNotNullParameter(completion, "completion");
            Function2 var3 = new <anonymous constructor>(completion);
            return var3;
         }

         public final Object invoke(Object var1, Object var2) {
            return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
         }
      }), $completion);
   }

   public final void show(@NotNull Data data) {
      Intrinsics.checkNotNullParameter(data, "data");
   }
}
**```**