深入理解Kotlin协程suspend工作原理(初学者也能看得懂)
1. 概述
挂起函数是Kotlin协程最重要的一个特性,所有其他概念都建立在它的基础上。所以我们需要深入了解它的工作原理。
挂起协程意味着在中间停止它。这类似于玩游戏,当我们想暂停游戏时,可以先存档,想继续游戏时,可以从存档处恢复游戏。当协程被暂停时,它会返回一个Continuation. 这就像游戏中的存档,协程可以使用Continuation从挂起的地方恢复。
请注意,这与线程非常不同,线程无法保存,只能阻塞。协程要强大得多,挂起时,它不消耗任何所在线程的资源。协程不一定需要在启动协程的线程上恢复,可以切换到不同的线程上。
2. 恢复
让我们看看它的实际效果。我们使用协程构建器(如runBlocking或launch)启动协程。suspend函数是可以挂起协程的函数。这意味着,它们必须在协程(或另一个挂起函数)上调用。
这是一个简单的程序,将打印“Before”和“After”。如果我们在中间调用协程标准库提供的suspendCoroutine函数会怎样呢?
如果你执行上面的代码,你将发现不会打印“After”,并且main函数不会退出。协程在“Before”之后暂停。我们的程序停止了,再也没有恢复。那我们怎么做呢?我们可以使用Continuation来恢复程序?
我们观察下suspendCoroutine调用,注意它以 lambda 表达式 ( { })结尾。作为参数传递的函数将在暂停之前被调用。此函数将Continuation作为参数。
观察打印日志,我们发现“After”仍然没有打印。我们可以用Continuation的resume方法让协程恢复执行。
请注意,上面示例中的“After”被打印出来,因为我们在suspendCoroutine中调用resume函数。
从 Kotlin 1.3 开始, Continuation的定义发生了变化。resumeWith函数代替了resume和resumeWithException函数。我们使用的resume和resumeWithException是标准库中的扩展函数。
我们还可以使用它来启动一个不同的线程,该线程将休眠一段时间后恢复:
我们还可以将启动线程的代码提取到一个函数中。
这种机制是有效的,但是我们也可以用线程池来代替线程。
暂停一段时间似乎是一个有用的功能。让我们把它提取成一个函数。我们将命名它delay。
这正是Kotlin协程库delay方法曾经的实现方式。目前的实现比较复杂,主要是为了支持测试,但是本质思路还是一样的。
3. 带值恢复
您可能需要注意的是我们为什么将Unit传递给resume函数,为什么我们将Unit作为suspendCoroutine函数泛型类型。Unit是suspendCoroutine函数的返回类型,也是Continuation的泛型类型。
当我们调用suspendCoroutine时,我们可以指定Continuation中的返回类型。resume函数需要调用与之相同的类型。
挂起对协程非常有意义。当我们做耗时操作时,我们需要被挂起。例如,当我们需要从API获取网络响应时,如果没有协程,这个线程就需要等待。因为线程很昂贵,这将是一个巨大的浪费。特别是当这是一个重要的线程,比如 Android 上的主线程。使用协程,它只是挂起协程,然后线程可以去做其他事情。一旦数据到了,线程将从协程挂起点恢复。
举个例子,我们模拟网络请求用户信息:
直接在main方法中调用suspendCoroutine不太方便。我们可以把它提取成一个方法。
目前,许多流行的库如Retrofit或Room已经支持suspend函数。这就是为什么我们很少需要在suspend函数中使用回调函数的原因。还有一个和suspendCoroutine类似的方法suspendCancellableCoroutine,我推荐你使用后者,后者支持取消功能。
你可能想知道如果API不给我们数据而是返回异常会怎样。如果服务死机或响应错误会怎样?。在这种情况下,我们不能返回数据,而是应该从协程挂起的地方抛出异常
4. 异常恢复
我们调用的每个函数都可能返回某个值或抛出异常。对于suspendCoroutine也是如此。我们可以调用resumeWithException从异常处返回。可以用try catch捕获异常。
5. 挂起一个协程,而不是一个函数
需要强调的一件事是我们只是暂停了一个协程,而不是一个函数。想象一下,我们将Continuation存储在某个变量中,并尝试在函数调用后恢复它。
这没有任何意义。resume永远不会被调用。
欢迎关注"字节小站"同名微信公众号。
深入理解Kotlin协程suspend工作原理(初学者也能看得懂)相关推荐
- pdf 深入理解kotlin协程_Kotlin协程实现原理:挂起与恢复
今天我们来聊聊Kotlin的协程Coroutine. 如果你还没有接触过协程,推荐你先阅读这篇入门级文章What? 你还不知道Kotlin Coroutine? 如果你已经接触过协程,但对协程的原理存 ...
- pdf 深入理解kotlin协程_协程初探
Hello,各位朋友,小笨鸟我回来了! 近期学习了Kotlin协程相关的知识,感觉这块技术在项目中的可应用性很大,对项目的开发效率和维护成本有较大的提升.于是就考虑深入研究下相关概念和使用方式,并引入 ...
- 【深入理解Kotlin协程】Google的工程师们是这样理解Flow的?
Question:why there is a Flow in kotlin? 问这个问题就好比在问为什么那里会有一座山存在,嗯,这貌似是一个哲学问题.当然,对于kotlin中的Flow的理解可能不会 ...
- pdf 深入理解kotlin协程_深入理解Kotlin协程
领取成功 您已领取成功! 您可以进入Android/iOS/Kindle平台的多看阅读客户端,刷新个人中心的已购列表,即可下载图书,享受精品阅读时光啦! - | 回复不要太快哦~ 回复内容不能为空哦 ...
- Kotlin协程:挂起与恢复原理逆向刨析
前言:只有在那崎岖的小路上不畏艰险奋勇攀登的人,才有希望达到光辉的顶点. --马克思 前言 经过前面两篇协程的学习,我相信大家对协程的使用已经非常熟悉了.本着知其然更要知其之所以然的心态,很想知道它里 ...
- 一文看透 Kotlin 协程本质
前言 公司开启新项目了,想着准备亮一手 Kotlin 协程应用到项目中去,之前有对 Kotlin 协程的知识进行一定量的学习,以为自己理解协程了,结果--实在拿不出手! 为了更好的加深记忆和理解,更全 ...
- 枯燥的Kotlin协程三部曲(上)——概念启蒙篇
0x0.引言 Kotlin 1.3 版本开始引入协程 Coroutine,简练的官方文档和网上一堆浅尝辄止的文章让我心里有些没底,不想止步于仅仅知道: ① Android中,Kotlin协程用于解决: ...
- 在 Android 开发中使用 Kotlin 协程 (一) -- 初识 Kotlin 协程
前言 最近在研究 Kotlin 协程,发现功能真的超级强大,很有用,而且很好学,如果你正在或计划使用 Kotlin 开发 Android,那么 Kotlin 协程你一定不能错过! 协程是什么? 我们平 ...
- 分析Kotlin协程只挂起不恢复会怎样(是否存在协程泄漏),以及挂起的协程存在哪里?
前言 刚开始正式学协程原理的时候(以前只是学api怎么用),大概是20年6月,也就是bennyhuo大佬出书<深入理解Kotlin协程>的时候,我买了本然后细细研究,我的内心就一直有一个问 ...
最新文章
- C#精髓 第四讲 GridView 72般绝技
- Java字节码instrument研究
- iOS系统网络抓包方法
- [IIS] [PHP] 500.19 随机出现
- @Aspect注解无效
- 自定义idea archetype
- bootstrap-table 新增可编辑行_现代Web开发堆栈工具DevExtreme 新增Gantt组件,助力项目管理...
- 基于Kmeans算法的文档聚类(包含Java代码及数据格式)
- 实体类里的内部类怎么单独赋值_java你还在用各种setter赋值初始对象吗?用设计模式化简为易...
- mysql error 1790_Mysql 数据恢复报错
- 中国制盐市场销售动态及需求潜力预测报告(新版)2022-2027年
- 高通平台fastboot下载
- (华师2021年秋季课程作业以及答案3)论述东西方文化差异对建筑风格的影响。
- 运维(6) Nacos开启连接密码安全认证
- 艾永亮:产品创新的重要性,创新的意义和思路
- fdisk:Linux 下管理磁盘分区的利器
- 《般若波罗蜜多心经》注解
- GitHub下载代理设置
- 计算各种面值人民币张数
- URLDownloadToFile缓存问题
热门文章
- C++学习笔记 C++11 std::chrono知识
- 电脑版微信怎么双开、多开 超级简单
- nacos界面定制化
- 计算机怎样发现路由器上u盘,路由器USB插口的4个功能,你也许一个都不知道!...
- 微信支付服务商,![CDATA[sub_mch_id与sub_appid不匹配],微信小程序支付,签名错误,CDATA[签名错误]解决方法,支付签名验证失败
- HTML5 canvas 行星环绕
- 如何编辑制作并发送手机报?
- 闲谈IPv6-IPv6地址聚类分配原则于源地址选择的关系
- Elasticsearch:如何在 Elastic Agents 中配置 Beats 来采集定制日志
- 02-07GRE真题及答案解析整理