kotlin 的 suspend fun 函数

更新日期: 2021-02-07 阅读次数: 6529 字数: 642 分类: Kotlin

在看 Android Room 的示例代码时,看到一些 DAO 中的操作函数前有 suspend 关键字。例如:

@Query("DELETE FROM word_table")
suspend fun deleteAll()

suspend 函数是 kotlin coroutine 引入的一个概念。

中文翻译

suspend, 中文意思是:挂起、推迟、悬浮。

suspend 是为解决什么问题而生

App 在发起网络请求拉取数据的同时,需要能保证用户在界面上的操作也能正常响应,界面可以刷新。 所以,就需要一套机制能保证耗时的 IO 操作,能与 UI 刷新操作同步执行。即,并行的概念。

UI 线程与其他 worker 线程的交互逻辑,可以参考

https://developer.android.com/codelabs/kotlin-android-training-coroutines-and-room#4

如果只是单纯的并行操作,并没有 suspend 什么事情。例如 A,B 两个耗时的操作,如果需要并行执行, 使用 launch 关键字启动两个 coroutine 就可以了。那为什么还需要 suspend 呢?

其适用场景是,B 操作的启动需要依赖 A 操作的结果。例如,A 操作执行本地 SQLite 数据库批量删除任务完成后, B 操作才能向服务器发起 HTTP 确认请求。类似于 js 中的 await 操作。

如何理解挂起一个函数

挂起,并不是说这个函数不需要执行了,而是将其挪到另外一个线程中进行执行。 这样就不会阻塞原有的线程,例如 UI 刷新线程。 待挂起线程执行完成,再返回原有线程。

为何有的 DAO 操作需要加 suspend

而有些不需要? select 不需要 suspend,而 insert update delete 需要?

这其实是个错觉,所有 Room DAO SQL 操作都需要加 suspend,只是使用 Flow 封装的不需要。但原理上是一样的。

By default, to avoid poor UI performance, Room doesn't allow you to issue queries on the main thread. When Room queries return Flow, the queries are automatically run asynchronously on a background thread.

suspend 函数如何被调用

suspend 函数有两种调用方式:

  • 被另一个 suspend 函数调用
  • 被 launch 调用。即在 coroutine 中调用 suspend 函数。

其他

  • kotlin coroutine 规避了 callback 回调的写法

参考

  • koltin 官方开发人员的一篇介绍: https://elizarov.medium.com/explicit-concurrency-67a8e8fd9b25
  • 讲解的非常清楚的一篇中文: https://kaixue.io/kotlin-coroutines-2/
  • https://developer.android.com/codelabs/kotlin-android-training-coroutines-and-room#4
  • https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式