最新要闻
- 嵩山少林塔沟武校学费_嵩山少林塔沟武校
- 《云顶之弈》网页版云游戏上线:PC互通 手机点开就能玩
- 环球快资讯丨最美“小丑女”演女主!《芭比》真人电影国内定档:7月21日上映
- 环球今头条!玩家哭了!女子带100张《塞尔达传说:王国之泪》卡带入境被海关查获
- 一之濑拓实和小松奈奈第一次见面(一之濑拓实)_天天快消息
- 今日视点:美股盘初:Adobe涨约5%,维珍银河涨超45%
- 普通人也能太空旅行 我国将推出商业航天项目:最快5年后|全球要闻
- 世界时讯:阿里总裁谈马云近况:他在东京教书 很开心
- 资讯:奥运冠军苏翊鸣获得清华大学保送资格 发文感谢:18岁三个愿望都实现了
- 法官曼司亚:一起离婚案件她跟踪回访了12年
- 向佐晒儿子周岁宴,现场紧搂郭碧婷秀恩爱,儿女露正脸都是高颜值_快资讯
- 江淮钇为3上市:最长续航600公里、8.99万元起_天天资讯
- 酷睿Ultra来了!Intel史上最混乱一代 还有马甲
- 谨慎下载 Win10 ISO镜像被黑客下马:攻击手法罕见_环球热消息
- 报道:博尔特4x100
- 今日热文:手握手的承诺 心贴心的服务_手握手
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
Kotlin协程-从理论到实战
上一篇文章从理论上对Kotlin协程进行了部分说明,本文将在上一篇的基础上,从实战出发,继续协程之旅。
从源头说起
在Kotlin中,要想使用协程,首先需要使用协程创建器创建,但还有个前提——协程作用域(CoroutineScope
)。在早期的Kotlin实现中,协程创建器是一等函数,也就是说我们随时随地可以通过协程创建器创建协程。但在协程正式发布以后,协程创建器需要在协程作用域对象上才能创建了,Kotlin添加了协程作用域来实现结构化并发。什么是结构化并发呢,通俗地说就是正确实施多个协程监控、管理的能力。在实际业务中,我们可能需要创建多个协程对象来完成不同的工作。为了对这些不相关的协程管理起来,Kotlin引入了协程作用域,通过某个协程作用域创建的协程都会被它管理着,在条件满足的时候,执行每个协程的取消工作或者结束自己。
(资料图片)
为了方便我们直接上手,官方提供了MainScope
和GlobalScope
供我们使用。正如名字那样,他们分别有不同的应用场景,前者比较适合用在UI相关的类中,而后者适用于在整个应用生命周期中都需要存活的类中。当然,对于Android开发者,其实我们有更好的选择——使用ViewModel
的Kotlin扩展,它不仅有着全部的协程作用域功能,开箱即用,而且还在onCleared
方法中实现了自动取消。
创建协程
有了协程作用域,那我们来创建一个最简单的协程吧。
viewModelScope.launch{ //这里就是协程代码啦啦啦啦 delay(2000) System.out.println("Hello World")}
launch
创建并启动了一个协程,协程启动两秒后,在控制抬打印了Hello World,然后协程就结束了(协程是有完整生命周期的)。这个协程完成的工作有限,我们可以使用线程完成相同的功能:
thread { Thread.sleep(2000) System.out.println("Hello World") }
我们可以看到,除去构建函数,两段代码唯一的区别就是延迟函数——delay
和Thread.sleep
.从功能上看他们都是让后面的代码延迟执行,但是效果却是不一样的,前者不会阻塞线程。这段代码其实是放在主线程里面执行的,但是它不会影响到UI的绘制,而后者假如把它放在主线程执行的话,应用会出现两秒的无响应。Kotlin把这种不会阻塞当前线程执行的函数称之为挂起函数,挂起函数可以在挂起点断开与当前线程的联系,让线程空闲下来完成其他的操作,当条件满足后,挂起函数重新在挂起点恢复,接着往下执行后面的代码。
还有个小问题没有解决,在上一篇文章中,我曾经说过,挂起函数只能在挂起函数中执行,既然delay
是挂起函数,那么反推,我们的代码块也应该是个挂起函数,而这个挂起函数就是所谓的协程体。
让协程跨线程工作
如果你看到上面的代码,然后转手在协程体里面写个网络请求的话,你会发现,你的应用崩溃了,这是怎么回事呢?因为协程虽然不会阻塞主线程,但是主线程是不允许进行网络请求的。如果这时你就急着下了协程没啥用的结论,那么你就肤浅了。让我们稍微改一改上面的代码,让它运行在子线程吧。
viewModelScope.launch (Dispatchers.IO){ //这里就是协程代码啦啦啦啦 delay(2000) System.out.println("Hello World")}
很好,现在协程体里面的网络请求可以顺利执行了,但是很快有读者就会发现新问题了——我怎么把网络请求的结果传回主线程呢,难不成还搞个Handler
,那和直接使用线程有什么区别,辣鸡协程。嘿,别急,这个协程其实也为客官处理好了。让我们再次改造一下代码:
viewModelScope.launch (Dispatchers.IO){ //这里就是协程代码啦啦啦啦,这里是在子线程执行的代码哦 //假装这个是网络请求吧 delay(2000) withContext(Dispatchers.Main) { //哦豁豁,这里竟然运行在主线程哦 System.out.println("Hello World") }}
很好,我们可以愉快地使用协程处理网络请求了,那么这些魔法是怎么发生的呢,停下脚步,我们来重新审视一下上面的代码。
首先,相比于最开始的代码,我们的代码里多了两个对象,一个方法调用。首先我们来看那两个对象,从名字中我们不难猜到它就是调度线程的。Kotlin提供了四个常用的实现
Default
,它是标准协程构建者默认使用的调度器,使用共享的线程池工作,适用于计算型的任务;Main
,它是代表UI线程的调度器,通常来说只有一个线程,使用这个调度器就可以直接在协程中操作UI;Unconfined
,它没有限定线程范围,它在哪个线程中被调用就会在哪个线程里执行完初始的代码,直到遇到挂起函数,随后它会使用挂起函数指定的调度器恢复,这个过程可以一直持续下去。IO
,是用来承载阻塞的IO操作的,如文件读写,网络连接等,是我们比较常用的调度器。
所以那两个调度器对象是让协程切换工作环境的魔法。接下来还有一个方法调用没有解释。withContext
的作用是将当前的协程调度器切换到指定的调度器上,用这个调度器接着执行构建块中的代码。同时它也是一个挂起函数。提到挂起函数,我们就该想到,它是可恢复的。所以当这个挂起函数的代码块执行完成之后,它会自动恢复成原来的调度器,接着往下执行。
用协程串联两个异步操作
在项目开发中,还有一种常见的应用场景,客户端需要先请求一些配置信息,然后利用配置信息再请求真正的内容信息。这个过程描述起来是串行的,但是代码写起来却是割裂的,需要在第一个网络请求的回调中处理和发起第二个请求,然后在第二个回调中获取真正需要展示的数据,可能这个过程还会加个存库,或者触发另外请求的工作,那么完了,这代码没法看了。这放在以前,这种情况通常会使用RxJava,但是RxJava的代码可读性也还是差点意思。那么Kotlin协程可以写成什么样呢?
viewModelScope.launch(Dispatchers.IO) { val retrofit=Retrofit.Builder().build() val apiUser=retrofit.create(APIUser::class.java) val user=api.current() val detail=api.userDetail(user.id) withContext(Dispatchers.Main) { userLiveData.value=detail } }
这和我们写一般的同步代码一摸一样,没有回调,也不需要付出其他代价,这个过程甚至可以一直加下去。其实我觉得这个才是协程的真正威力。
让多个协程一起工作
我们继续复杂化使用场景——我在做一个多端使用的笔记App,现在用户打开了某一个已存在的笔记,为了让用户能快速浏览到上一次的操作信息,一方面我需要从文件中读取上一次操作的结果,另一方面我要拉取远程的操作结果,然后对两个结果合并,决定最终的展示数据。考虑到这两个操作其实是并行的,上面我们让协程串联起来的思路已经不适用了,因为协程里面的操作都是串行的。既然一个协程解决不了,我们再加一个协程可不可以呢?看着好像是可以,但是,协程操作的结果我们怎么获取到呢?查阅API,我找到了另一个协程构建器async
。它会返回一个协程对象,然后通过await
方法获取到协程的计算结果。思路来了,我们马上动手
val fileResult=viewModelScope.async(Dispatchers.IO) { //假装是读文件的代码吧 1 } val networkResult=viewModelScope.async(Dispatchers.IO) { //也是假装是网络请求的代码 2 } val fResult=fileResult.await()val rResult=networkResult.await()val result=if(fResult>rResult){ fResult}else{ networkResult}
然后你就会发现报错了,await
是挂起函数。看来两个协程还完成不了,要三个,所以,让我们创建第三个协程吧
//前面的两个协程不变 viewModelScope.launch { val fResult=fileResult.await() val rResult=networkResult.await() val result=if(fResult>rResult){ fResult }else{ networkResult }}
这就是协程间通信的基本写法啦,从这个基础之上,甚至还能衍生出更复杂的版本,但是万变不离其宗,都可以参考这种思路完成。
协程的取消
正如之前提到的一样,协程有着类似于线程的完整生命周期,包括创建,激活,完成中(取消中),已完成(已取消),刚才我们的示例都是正常状态,协程完成工作后会自动结束,但协程的另一条取消流程我们还没有提到。协程有自己的取消API——cancel
可供使用,我们只需要保存好协程创建者返回的协程对象就行了。当然更常见的还是文章开篇提到的使用协程作用域取消。这个操作会取消所有的协程。
总结
本篇文章从协程创建开始,讲到了怎样用协程写出异步代码,怎么让多个协程共同工作,虽然覆盖了很大一部分使用场景,但是依然还有遗漏。由于篇幅限制,遗漏部分将在下一篇博文中继续讲解,希望大家持续关注。
青山不改,绿水长流,咱们下期见!
关键词:
Kotlin协程-从理论到实战
常见WebShell的流量特征
今日报丨01. 组建知识星球服务体系
嵩山少林塔沟武校学费_嵩山少林塔沟武校
《云顶之弈》网页版云游戏上线:PC互通 手机点开就能玩
环球快资讯丨最美“小丑女”演女主!《芭比》真人电影国内定档:7月21日上映
环球今头条!玩家哭了!女子带100张《塞尔达传说:王国之泪》卡带入境被海关查获
一之濑拓实和小松奈奈第一次见面(一之濑拓实)_天天快消息
今日视点:美股盘初:Adobe涨约5%,维珍银河涨超45%
普通人也能太空旅行 我国将推出商业航天项目:最快5年后|全球要闻
世界时讯:阿里总裁谈马云近况:他在东京教书 很开心
资讯:奥运冠军苏翊鸣获得清华大学保送资格 发文感谢:18岁三个愿望都实现了
法官曼司亚:一起离婚案件她跟踪回访了12年
当前关注:聊聊Flink必知必会(四)
【世界快播报】Kotlin协程-从一到多
金科地产8.8亿元债券本息未按期偿付 持有人会议仍在表决中 新动态
向佐晒儿子周岁宴,现场紧搂郭碧婷秀恩爱,儿女露正脸都是高颜值_快资讯
江淮钇为3上市:最长续航600公里、8.99万元起_天天资讯
酷睿Ultra来了!Intel史上最混乱一代 还有马甲
谨慎下载 Win10 ISO镜像被黑客下马:攻击手法罕见_环球热消息
报道:博尔特4x100
LGV引理
【世界新要闻】Docsify on VPS,搭建最简个人博客
先正达集团IPO过会 沪市主板即将迎来全球农业龙头企业
今日热文:手握手的承诺 心贴心的服务_手握手
男孩玩氢气球砸到吹风机爆燃 妈妈被严重烧伤:画面触目惊心
美国能源部资助Intel 1220万元:开发2000W散热技术-天天热资讯
狂喝红牛能抗老?
不忘挖井人!奔驰Vision One-Eleven概念车首发:致敬经典实验车|天天速读
刷新纪录!41颗卫星共乘一枚火箭座位怎么排:全靠它了
精选!蜂蜜的种类
结案了!in到底用不用索引,啥时候能用啥时候不能用-天天新消息
lua中 . 和 : 的区别
港人北上消费升温 香港零售业对人流量持乐观态度_世界新消息
前沿资讯!欧盟机构:6月初全球平均气温创纪录
世界百事通!理想MPV设计手稿曝光 李想:设计灵感不是和谐号 而是鲸鱼
女儿高考完提出3个要求妈妈崩溃:养了个祖宗|天天速看
土星卫星首次发现高浓度磷元素 地外生命真的存在?
美商海盗船发布新款DARKSTAR鼠标:15个可编程按键
2399元的RTX 4060即将开卖 专家称英伟达还得涨:显卡份额突破76%
[路演]金杨股份首次公开发行股票并在创业板上市网上路演今日在全景网成功举办
世界简讯:网易云心动模式为什么会播不是喜欢的音乐(网易云的心动模式在哪)
元数据在数字化时代中的应用与发展
记录--设计一个可选择不连续的时间范围的日期选择器
聊聊Flink的必知必会(三)
【活动访谈】发力数字基座 推动物联创新—航天科技控股集团AIRIOT4.0平台发布会活动专访 天天短讯
即时焦点:曝光!Apache SeaTunnel Catalog 功能设计为何能大大简化用户启用步骤?
财政部:1-5月全国一般公共预算收入同比增长14.9% 一般公共预算支出同比增长5.8%
新美男记_关于新美男记简介
当前资讯!高考考生们这些“套路”骗局要当心:千万别信
环球观热点:小哥十米高跳江救人!老家张家界奖励10万元外加一套房
16针显卡供电接口闯大祸!第一次把电源烧了
全球实时:HDD硬盘被垄断 倪光南院士:SSD取代的时机到了
iPhone 15 Pro Max影像这下拉满了!看不到短板
景区观光车这价格,吃相太难看了
环球热讯:两部门印发文件部署高校毕业生档案转递接收工作
Kubernetes 1.27.2集群安装|每日热讯
单体服务,微服务服务的演变 & 各自优缺点
世界观焦点:javaScript基础语法之正则表达式
国网集安市供电公司:开展端午节前作风建设监督检查
世界要闻:比法拉利更抢眼!理想设计师亲自“泄密” W01设计手稿公布
苦中作乐!广东暴雨积水成河:有人屋内钓鱼 外卖车成水上摩托-当前滚动
快报:顾客遇账单刺客8碗米饭要90元 餐厅反驳:为了拍段子蹭流量
热到怀疑人生!今年“烧烤模式”来得早
每日视讯:RTX 4080显卡杀到8399元 铭瑄618全程价保:硬核装备开抢
FOreverLove什么意思中文
全球热门:远程办公篇-vscode远程SSH开发
和必应对话之mysql分区分表
天天日报丨位运算与集合
镜像,容器,容器数据卷,DockerFile 相关命令 使用总结 全球资讯
今日视点:胸部怎样才算不下垂_胸部怎样才能变大
全球今日讯!Facebook首席AI专家表示, 大语言模型只是昙花一现
好多明星去看了梅西比赛:陈妍希、苏醒等人都在现场_全球快播
世界看热讯:余承东:比亚迪是未来能活下来的巨头之一 华为能帮车企活下来
余承东:问界M5智能驾驶能力全球第一 超越特斯拉、国内外所有同行 天天快播
李一男造车梦“复活”自由家NV换标大乘V07已通过工信部申报
全球要闻:一口降温夏日必备!迷你可爱多冰淇淋官旗发车:每支不到1块钱
【天天速看料】邓一杰:黄金破1962,保守调仓,激进持仓!
当前头条:冬天适合在室内养什么植物_冬天室内养什么植物好 冬天适合室内种植的植物介绍
梅西ins发文感谢中国粉丝:开场81秒就进球 打破职业生涯记录 快看点
离谱!代驾设套碰瓷13名代驾同行:故意选土路蹭底盘 世界快消息
梅西直播被吐槽广告多?回应来了:纯聊天 没有带货_每日热议
苹果iPhone为何只有27W充电?原因可能有三 焦点速读
韩媒:韩国年轻人迷上中国App无法自拔 实在太好用了-全球讯息
速看:液冷概念股震荡走高 飞龙股份拉升封板
天天微头条丨CHAT-GPT初使用
唐源电气6月16日盘中跌幅达5%
男子突发奇想将甜瓜和西瓜嫁接 网友看完大笑:这是焊接_每日观察
环球观焦点:交通拥堵为何不禁私家车?这座一线城市要限电动自行车 只是试运行 专家吐槽
罕见!巨鸟撞碎玻璃卡在飞机舱,飞行员满脸血仍淡定驾驶……_全球今热点
热点!从0开始,精通Go语言Rest微服务架构和开发
Apache Spark教程_编程入门自学教程_菜鸟教程-免费教程分享
Qt+QtWebApp开发笔记(六):http服务器html实现静态相对路径调用第三方js文件
【环球聚看点】实力登场 汉马动力携四款动力产品亮相上海GPOWER 2023动力展
陕西加强养老服务设施规划建设新建城区 新建居住(小)区配建养老服务设施
员工没完成业绩被罚吃苦瓜 公司:激励团队 都是自愿的
最新消息:买2套到手23件:黑人好来超白茶牙膏套装5支39.9元
坦克300坐不住了 全新一代北京BJ40曝光 你会选谁?
环球观热点:RTX轻薄本怎么选?不妨看看这三款:13499元的华硕灵耀Pro14 2023无可挑剔
世界观察:维珍银河计划月底进行首次商务飞行:数百名旅客将上太空