当前位置: 首页 > news >正文

android kotlin 协程(五) suspend与continuation

android kotlin 协程(五) suspend与continuation

通过本篇你将学会:

  • suspendCoroutine{}

  • suspendCancellableCoroutine{}

  • suspend 与 continuation

suspendCoroutine

第一次看到这玩意的时候肯定有点身体不适, 先不用管这个东西是什么,

目前为止 只需要知道 suspendCoroutine是一个函数即可

先来想想如果不用这个suspendCoroutine ,遇到一个网络请求的原始写法是怎么样的

通常情况下,我们请求一个接口,至少需要处理2种情况

  • 成功返回
  • 失败返回

来看例子:

private suspend fun requestLoginNetworkData(account: String, pwd: String) =withContext(Dispatchers.IO) {delay(2000)// 模拟请求耗时if (account == "123456789" && pwd == "666666") {Result.success("登陆成功")} else {Result.failure(Throwable("登陆失败"))}}fun main() = runBlocking<Unit> {val deferred = async {// 模拟网络请求requestLoginNetworkData("987654321", "666666")}// 获取网络返回数据,判断成功与失败val result = deferred.await()// result.getOrDefault("") // 如果返回错误使用 默认值// result.getOrThrow() // 如果返回错误使用 错误// result.getOrNull() // 如果返回错误使用 nullresult.onSuccess {println("登陆成功:${result.getOrNull()}")}.onFailure {println("登陆失败:${result.getOrNull()}")}
}

在这段代码中,我们模拟网络请求, 给一个错误的帐号密码,最终打印结果为

登陆失败:null

通过前几篇的了解,这个例子应该是非常简单的

来看看使用 suspendCoroutine怎么玩

private suspend fun <T> requestLoginNetworkData(account: String, pwd: String): String {return withContext(Dispatchers.IO) {delay(2000)  // 模拟网络耗时需要2sreturn@withContext suspendCoroutine {if (account == "123456789" && pwd == "666666") {it.resume("登陆成功")} else {it.resumeWithException(RuntimeException("登陆失败"))}}}
}suspend fun main() = runBlocking {val scope = CoroutineScope(Dispatchers.IO)// 开启一个协程val deferred = scope.async {// 模拟网络请求requestLoginNetworkData<String>("987654321", "666666")}// 获取网络返回数据,判断成功与失败val result = runCatching {deferred.await()}if (result.isSuccess) {printlnThread("登陆成功:${result.getOrNull()}")} else {printlnThread("登陆失败:${result.exceptionOrNull()}")}
}

好像使用suspendCoroutine 之后代码变得更多了?

来看看两段代码的区别:

image-20230221144750274

这两段代码,只不过是回调方式不同!

那么是否可以理解为 suspendCoroutine 本质就是一个回调呢?

没错! 暂时可以理解为:suspendCoroutine 就是一个回调

再来看看 suspendCoroutine的具体实现

image-20230221145402455

其本质就是一个Continuation

tips: Continuation 这个角色特别重要,Continuation 是用来使挂起函数恢复执行状态的

就是传说中: kotlin挂起于恢复中的 恢复

再来看看调用的方法:

image-20230221145610113

  • resume 恢复正确
  • resumeWithException 恢复错误

目前不理解恢复没关系, 先理解为就是一个接口回调

  • resume 回调正确
  • resumeWithException 回调错误

suspendCoroutine 的本质作用是创建一个挂起点,它会将当前协程挂起,并将协程的执行权交给调用方函数。同时,它会传入一个 Continuation 对象,该对象包含了协程的上下文和协程恢复后需要执行的操作。调用方函数可以在执行完必要的操作后,调用该 Continuation 对象的 resume 方法,来唤醒协程并继续执行。

suspendCoroutine 是一个非常重要的函数,它可以让我们将异步操作转化为同步代码风格

说的直白一点就是:

  • 不使用 suspendCoroutine 执行一个suspend的函数的时候, 恢复工作由系统完成

  • 使用 suspendCoroutine会将系统的恢复工作抢过来,可以通过 continuation#resume() 来自己恢复

例如这样,我们手动处理了 suspendCoroutine,但是没有恢复, 就会无限挂起

image-20230221151954694

我们知道在kotlin中有suspend,但是在java中并没有suspend关键字,

那么kotlin suspend函数反编译成java后是什么样的

image-20230221152627482

可以看出,suspend关键字并没有任何作用, 他的唯一作用就是告诉开发者,我这里需要挂起罢了

真实干活的其实是 Continuation!

现在你还觉得 suspendCoroutine 仅仅只是一个回调嘛?

suspendCoroutine 不仅可以控制suspend函数的恢复,而且还可以让异步的代码同步化.

最关键的是线程, 线程安全不用我们担心.

来比较一下同步代码与异步代码的风格写法:

image-20230221160111473

也没说异步写法不好,黑猫白猫,抓住老鼠就是好猫,但是这只是一个请求,如果说 逻辑很多,嵌套很深的话,代码会不会成这样:

IMG_7411

suspendCancellableCoroutine

suspendCoroutine 与 suspendCancellableCoroutine 的区别:

suspendCancellableCoroutine 相当于是对 suspendCoroutine 的一次封装, 增加了一些 状态,以及 可以 cancel了

  • isActive 是否活跃
  • isCancelled 是否取消
  • isCompleted 是否执行完成

还记得这三个状态吗? Job中也有这三个状态!

suspendCancellableCoroutine 增加了 invokeOnCancellation , 该方法用来监听协程取消, 当协程被取消的时候会被回调

来看看下面的例子:

image-20230222174735212

可以看到,invokeOnCancellation 并没有执行,这里也很好理解,因为没有cancel不执行也正常

在换一个例子

image-20230222141656317

这里的关键点是await, 这是官方的一个扩展,来看看:

image-20230222141919812

这段代码对Cell扩展了一下, 请求数据的时,

  • 请求成功 就恢复
  • 请求失败 也恢复,只不过会throw异常

当协程取消的时候,将okhttp cancel掉

invokeOnCancellation 注意事项

在使用suspendCancellableCoroutine的时候,有一个方法 invokeOnCancellation

这个方法用来监听当前作用域是否取消

先来看看运行的3种状态:

  • isActive 是否活跃
  • isCancelled 是否取消
  • isCompleted 是否执行完成

image-20230222190707683

当我们调用 Continuation#resume()恢复之后, 当前协程就会被标记为完成状态

这里有一个小细节:Continuation#cancel() 只能cancel未完成或在进行中的协程, 如果协程一旦执行完成,也就是一旦恢复,那么 invokeOnCancellation则不会被调用

再来看看取消:

image-20230222193217557

这种情况,应该大家看看就会了很好理解

还有一种写法, 我们知道,当我们cancel父协程的时候,所有子协程也会被cancel,那么我们就可以利用这个特性,来完成这个效果

例如这样:

image-20230222201240817

这里有一个很关键的点,折磨了我很久:)

当一个挂起函数中的suspendCancellableCoroutine函数被恢复(例如,通过调用continuation.resumecontinuation.resumeWithException)后,该协程就不再挂起,并且不能再被取消。因此,在恢复之后,该协程将无法响应invokeOnCancellation函数。

完整代码

下篇开始会看看协程源码, 以及手动创建协程等

下篇预告:

  • SafeContinuation
  • startCoroutine
  • createCoroutine
  • receiver startCoroutine
  • receiver createCoroutine

原创不易,您的点赞就是对我最大的支持!

相关文章:

android kotlin 协程(五) suspend与continuation

android kotlin 协程(五) suspend与continuation 通过本篇你将学会: suspendCoroutine{} suspendCancellableCoroutine{} suspend 与 continuation suspendCoroutine 第一次看到这玩意的时候肯定有点身体不适, 先不用管这个东西是什么, 目前为止 只需要知道 suspendCoro…...

JavaScript事件循环

大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库一、异步执行原理1. 单线程的JavaScript我们知道&#xff0c;JavaScript是一种单线程语言&#xff0c;它主要用来与用户互动&#xff0c;以及操…...

华为OD机试真题Python实现【最少停车数】真题+解题思路+代码(20222023)

最少停车数 题目 特定大小的停车场 数组cars表示 其中1表示有车0表示没车 车辆大小不一,小车占一个车位(长度1) 货车占两个车位(长度2) 卡车占三个车位(长度3) 统计停车场最少可以停多少辆车 返回具体的数目 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Pyt…...

Python每日一练(20230223)

目录 1. 合并区间 2. 单词接龙 3. N皇后 附录&#xff1a;回溯算法 基本思想 一般步骤 1. 合并区间 难度&#xff1a;★★ 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回…...

Flask----------第一个flask项目,debug、host、port的配置

目录 1.flask 1.简介 2.flask框架的优势 2.第一个flask项目 3.debug 开启debug方法 1.专业版 2.社区版 4.修改host 5. 修改port端口 1.flask 1.简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架&#xff0c;对于Werkzeug本质是So…...

容器技术概述

容器技术概述 软件应用程序通常依赖于运行时环境提供的其他库、配置文件或服务。软件应用程序的传统运行环境是物理主机或虚拟机&#xff0c;应用程序依赖项作为主机的一部分安装。 例如&#xff0c;考虑一个 Python 应用程序&#xff0c;它需要访问实现 TLS 协议的公共共享库…...

「SAP」ABAP模块学习需要了解什么?快收下这份ABAP技术栈指南【附技能树】

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计专业大二本科在读&#xff0c;阿里云社区专家博主&#xff0c;华为云社区云享专家&#xff0c;CSDN SAP应用技术领域新兴创作者。   在学习工…...

【python 基础篇 九】python的常用数据类型操作-------时间日历

目录1.python时间操作1.1 time模块1.2 calendar模块1.3 datetime模块1.python时间操作 python程序能用很多方式处理日期和时间&#xff0c;转换日期格式也是一个常见功能。 1.1 time模块 ​ 提供了处理时间和表示之间转换的功能 获取当前时间戳 概念&#xff1a;从0时区的1…...

华为OD机试真题Python实现【相同字符连续出现的最大次数】真题+解题思路+代码(20222023)

相同字符连续出现的最大次数 题目 输入一串字符串 字符串长度不超过100 查找字符串中相同字符连续出现的最大次数 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 输入只有一行,包含一个长度不超过100的字符串 输出描述 输出只…...

【Unity3D】空间和变换

1 空间 1.1 左右手坐标系及其法则 1.1.1 左右手坐标系 左手坐标系与右手坐标系Unity 局部空间、世界空间、裁剪空间、屏幕空间都采用左手坐标系&#xff0c;只有观察空间采用右手坐标系。 左右手坐标系除了坐标系朝向&#xff08;旋向性&#xff09;不同&#xff0c;还存在以…...

脑洞|ChatGPT加持下,ChatOps将如何革新团队协作与运维管理?

要说近期科技圈 “顶流”&#xff0c;非 ChatGPT 莫属。 比起目前常见的语音助手与聊天 bot&#xff0c;这位机器人显得更有 “人味儿”&#xff0c;不仅能模拟人类的语气&#xff0c;跟你聊得有来有回&#xff0c;还能写剧本、编音乐、写代码。 说到聊天工具&#xff0c;就让…...

华为OD机试真题Python实现【找数字】真题+解题思路+代码(20222023)

找数字 题目 给一个二维数组nums,对于每一个元素num[i],找出距离最近的且值相等的元素,输出横纵坐标差值的绝对值之和,如果没有等值元素,则输出-1。 例如: 输入数组nums为 0 3 5 4 2 2 5 7 8 3 2 5 4 2 4对于 num[0][0] = 0,不存在相等的值。 对于 num[0][1] = 3,存…...

【Database-01】达梦数据库Docker版下载安装

1、前往达梦数据库官网下载 https://www.dameng.com/1.1、选择数据库 - 数据库产品系 1.2、选择 达梦数据库管理系统&#xff08;DM8&#xff09; 1.3、点击试用下载 1.4、注册达梦账户 1.5、选择DM8 Docker镜像 https://www.dameng.com/list_103.html1.6、或者使用以下网址也…...

Allegro如何打开格点显示效果操作指导

Allegro如何打开格点显示效果操作指导 Allegro可以设置格点显示效果,以格点来判定走线等等是否都处于格点上,如下图 如何打开格点显示效果,具体操作如下 点击Setup点击Grids...

电子技术——反馈放大器的分析方法总结

电子技术——反馈放大器的分析方法总结 第一种也是最简单的估算方法&#xff0c;直接拿出反馈网络&#xff0c;计算 β\betaβ 则假设在 AβA\betaAβ 无限大的情况下有 Af≃1/βA_f \simeq 1/\betaAf​≃1/β 。开环法。比第一种方法更能精确的估计 AAA 和 β\betaβ 的值。系…...

微服务系统启动,环境从0开始的搭建过程

1. JDK的下载安装&#xff08;傻瓜式&#xff09; 安装过程傻瓜式&#xff0c;直接一步到位。我安装的版本为&#xff1a;jdk-17_windows-x64_bin 2. 集成开发工具的下载安装&#xff1a;IDEA&#xff08;傻瓜式&#xff09; ideaIU-2021.2.1 网上资源很多&#xff0c;自己找…...

手工测试1年经验面试,张口要13K,我真是服了····

由于朋友临时有事&#xff0c; 所以今天我代替朋友进行一次面试&#xff0c;他需要应聘一个测试工程师&#xff0c; 我以很认真负责的态度完成这个过程&#xff0c; 大概近30分钟。 主要是技术面试&#xff0c; 在近30分钟内&#xff0c; 我与被面试者是以交流学习的方式进行的…...

【保姆级】手把手捋动态代理流程(JDK+Cglib超详细源码分析)

简介动态代理&#xff0c;通俗点说就是&#xff1a;无需声明式的创建java代理类&#xff0c;而是在运行过程中生成"虚拟"的代理类&#xff0c;被ClassLoader加载。 从而避免了静态代理那样需要声明大量的代理类。上面的简介中提到了两个关键的名词&#xff1a;“静态…...

Appium自动化测试 Inspector定位Webview/H5页面元素

目录操作步骤Python操作该混合App代码Appium在操作混合App或Android App的H5页面时, 常常需要定位H5页面中的元素, 传统方式是 FQ 使用Chrome://inspect来定位元素, 环境准备相当繁琐, 不仅需要想办法FQ, 而且还需要Android设备安装Google框架以及手机版Chrome浏览器以及相应的…...

数组求和方法总结,学点干货

1.循环 &#xff08;新手用&#xff09; 1.1 普通for 循环 简单质朴 const arr [1, 2, 3, 4, 5];let sum 0;for (let i 0; i < arr.length; i) {sum arr[i];}1.2 for in 循环 与普通for循环大同小异 const arr [1, 2, 3, 4, 5];let sum 0;for (let i in arr) {sum …...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...