协程 - 挂起和恢复

相关链接

协程是什么

并发设计模式,可以简化异步执行的代码

协程能做什么

协程可以用来执行异步任务

和线程有什么区别,看扔物线的课程说,kotlin 协程就是线程,而线程意味者 CPU 资源, cpu 的时间片

怎么使用

launch({ val user = api.getUser() // 👈 网络请求(IO 线程) nameTv.text = user.name // 👈 更新 UI(主线程) })

launch 函数加上实现在 {} 中具体的逻辑,就构成了一个协程。

  • 挂起函数是什么

    协程中的一种函数,在执行到 suspend 函数时,主线程暂停执行协程中的剩余代码

    那函数挂起以后呢,谁来执行呢? 由挂起函数指定,一般都需要指定子线程(IO),不然挂起没有意义

    也就是协程可以用来做异步任务并且不用写很多回调了

  • Suspend 修饰

    挂起函数的使用也有一些限制,比如只能在协程中或者其他挂起函数中使用

挂起和恢复

  • 挂起是函数的挂起,相当于 return
  • 恢复也是函数的恢复,相当于 callback

当使用 suspend 声明一个挂起函数时,有点类似注解,告诉编译器需要实现一些代码,从协程的源码中是很难了解到它的原理的,需要观察编译后的产物

示例查看的步骤:

kotlin 复制代码
suspend  fun  testCoroutine(){
    Log.e("打印","测试 delay 前")
    delay(2000)
    Log.e("打印","测试 delay后打印")
 }

编译后的结果

php 复制代码
   @Nullable
   public final Object testCoroutine(@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;
            }
         }

         $continuation = new ContinuationImpl(var1) {
            // $FF: synthetic field
            Object result;
            int label;
			// 唤醒 -  continuation 回调执行 invokeSuspend
			// 内部执行了我们的 testCoroutine() 
            @Nullable
            public final Object invokeSuspend(@NotNull Object $result) {
               this.result = $result;
               this.label |= Integer.MIN_VALUE;
               return MainActivity.this.testCoroutine(this);
            }
         };
      }

      Object $result = ((<undefinedtype>)$continuation).result;
      Object var4 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      switch (((<undefinedtype>)$continuation).label) {
         case 0:
            ResultKt.throwOnFailure($result);
            Log.e("打印", "测试 delay 前");
            ((<undefinedtype>)$continuation).label = 1;
			// 这里挂起就是直接 return 了
			// var4 就是 COROUTINE_SUSPENDED
            if (DelayKt.delay(2000L, (Continuation)$continuation) == var4) {
               return var4;
            }
            break;
         case 1:
            ResultKt.throwOnFailure($result);
            break;
         default:
            throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }

      Log.e("打印", "测试 delay后打印");
      return Unit.INSTANCE;
   }

怎样改造原有代码

落到应用上,怎样使用协程来改造我们的旧项目代码呢?

  • 方式一
java 复制代码
/** 举例
** fun parseFile()
**/
lifecyclesScope.launch{
    val fileContent = lifecyclesScope.async{
        parseFile().await()
    }
    println(fileContent)
}

这种方式通过调用 await() 来等待方法执行结束,不过每次都要自行再包一层 async{},并且还要带要调用一下 await() 有点不太优雅

这里补充一下,async 会开启线程来执行任务,内部的线程池的核心线程数为 ==2== ,最大线程数为 ==cpu 核心数==

  • 方式二
kotlin 复制代码
    lifecyclesScope.launch{
    val fileContent = parseFile()
    println(fileContent)
    }

    /\*\*

    *   改造 parseFile 内部
        \*\*/
        suspend fun parseFile(){
        // 编译以后就会变成 CoroutineSuspended
        // 执行会挂起
        return suspendCanceableCoroutine{ continuation->
        Thread{
        //... io
        continuation.resumeWith(Result.success("xxxxx"))
        }.start()
        }
        }

    // 这种方式类似 delay() 的实现

    public suspend fun delay(timeMillis: Long) {
    if (timeMillis <= 0) return // don't delay
    return suspendCancellableCoroutine sc@ { cont: CancellableContinuation&lt;Unit&gt; ->
    // if timeMillis == Long.MAX\_VALUE then just wait forever like awaitCancellation,      		don't schedule.
    if (timeMillis < Long.MAX\_VALUE) {
    cont.context.delay.scheduleResumeAfterDelay(timeMillis, cont)
    }
    }
    }

这种方式是通过使用 suspendCancellableCoroutine 包裹我们原有的代码块,在执行完成后 resumeWith 返回结果

Retrofit 在 2.8 以后,通过扩展 Call 支持 await() ,内部也是用 suspendCancellableCoroutine 来实现的

相关推荐
limuyang214 小时前
PDF Viewer KMP(基于 chrome 的 PDFium 内核)
android·kotlin
pengyu21 小时前
【Kotlin 协程修仙录 · 大乘境 · 初阶】 | 跳出三界:协程在 KMP 与后端开发中的跨平台之道
android·kotlin
XiaoLeisj1 天前
Jetpack Compose 知识点
android·kotlin·android jetpack·compose
Kapaseker1 天前
Compose SelectionState API — 主动控制文本选择
android·kotlin
小强闯江湖2 天前
不只是让 AI 写代码:ViewCompose 把 Android UI 做成了可编译、可渲染的闭环
android·人工智能·kotlin
bytebitx3 天前
MacOS 编译腾讯 Mars XLog 及使用(已16KB对齐)
kotlin·mac·apk
alexhilton4 天前
让架构边界变成可执行的测试
android·kotlin·android jetpack
数据治理自习室4 天前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
名剑走天下5 天前
Android 面试题大全
android·kotlin
chjif5 天前
Android 设备管控开发实战:自定义 Launcher 如何只显示指定 App?
android·kotlin