Kotlin Vocabulary | 揭秘协程中的 suspend 修饰符

本文探讨 Kotlin 协程中的 `suspend` 修饰符,揭示其底层工作原理。通过编译器如何将挂起函数转换为状态机,理解挂起函数如何在不阻塞线程的情况下实现异步操作。文章还介绍了 Continuation 接口和不同 Dispatcher 的作用,帮助开发者更深入地掌握协程的工作方式。
摘要由CSDN通过智能技术生成

Kotlin 协程把 suspend 修饰符引入到了我们 Android 开发者的日常开发中。您是否好奇它的底层工作原理呢?编译器是如何转换我们的代码,使其能够挂起和恢复协程操作的呢?

了解这些将会帮您更好地理解挂起函数 (suspend function) 为什么只会在所有工作完成后才会返回,以及如何在不阻塞线程的情况下挂起代码。

本文概要: Kotlin 编译器将会为每个挂起函数创建一个状态机,这个状态机将为我们管理协程的操作!

???? 如果您是 Android 平台上协程的初学者,请查阅下面这些协程 codelab:

  • 在 Android 应用中使用协程

    https://codelabs.developers.google.com/codelabs/kotlin-coroutines/#0

  • 协程的进阶使用: Kotlin Flow 和 Live Data

    https://codelabs.developers.google.com/codelabs/advanced-kotlin-coroutines/#0

协程 101

协程简化了 Android 平台的异步操作。正如官方文档《利用 Kotlin 协程提升应用性能》所介绍的,我们可以使用协程管理那些以往可能阻塞主线程或者让应用卡死的异步任务。

  • 《利用 Kotlin 协程提升应用性能》

    https://developer.android.google.cn/kotlin/coroutines

协程也可以帮我们用命令式代码替换那些基于回调的 API。例如,下面这段使用了回调的异步代码:

// 简化的只考虑了基础功能的代码
fun loginUser(userId: String, password: String, userResult: Callback<User>) {
  // 异步回调
  userRemoteDataSource.logUserIn { user ->
    // 成功的网络请求
    userLocalDataSource.logUserIn(user) { userDb ->
      // 保存结果到数据库
      userResult.success(userDb)
    }
  }
}

上面的回调可以通过使用协程转换为顺序调用:

suspend fun loginUser(userId: String, password: String): User {
  val user = userRemoteDataSource.logUserIn(userId, password)
  val userDb = userLocalDataSource.logUserIn(user)
  return userDb
}

在后面这段代码中,我们为函数添加了 suspend 修饰符,它可以告诉编译器,该函数需要在协程中执行。作为开发者,您可以把挂起函数看作是普通函数,只不过它可能会在某些时刻挂起和恢复而已。

不同于回调,协程提供了一种简单的方式来实现线程间的切换以及对异常的处理。但是,在我们把一个函数写成挂起函数时,编译器在内部究竟做了什么事呢?

Suspend 的工作原理

回到 loginUser 挂起函数,注意它调用的另一个函数也是挂起函数:

suspend fun loginUser(userId: String, password: String): User {
  val user = userRemoteDataSource.logUserIn(userId, password)
  val userDb = userLocalDataSource.logUserIn(user)
  return userDb
}


// UserRemoteDataSource.kt
suspend fun logUserIn(userId: String, password: String): User


// UserLocalDataSource.kt
suspend fun logUserIn(userId: String): UserDb

简而言之,Kotlin 编译器会把挂起函数使用有限状态机 (稍后讲到) 转换为一种优化版回调。也就是说,编译器会帮您实现这些回调!

  • 有限状态机

    https://en.wikipedia.org/wiki/Finite-state_machine

Continuation 接口

挂起函数通过 Continuation 对象在方法间互相通信。Continuation 其实只是一个具有泛型参数和一些额外信息的回调接口,稍后我们会看到,它会实例化挂起函数所生成的状态机。

  • Continuation

    https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/-continuation/index.html

  • Continuation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值