android kotlin 协程(六) 源码浅析

news2024/9/28 7:24:07

android kotlin 协程(六) 源码浅析

前言: kotlin协程源码十分庞大, 本篇只能吧我理解的源码聊一聊,不会特别深入研究,只会浅浅的看看表层. 本来计划协程系列是10篇左右,后续是flow热流冷流之类的, 冷流操作符之类的应该不会在写了, flow当作Rxjava来用就可以,后续可能还会写一篇关于热流的文章. 也可能没有:) 主要是不好写,文字写出来还是比较生硬…

如果没有看过前几篇,建议先看看前几篇, 本篇遇到前几篇的知识不会重复说!

launch 浅析

源码阅读从最简单的一个launch开始!

image-20230227135052971

在launch的时候, 会执行 CoroutineScope.newCoroutineContext函数 这里会传入一个EmptyCoroutineContext

CoroutineScope.newCoroutineContext 会走 foldCopies , 这个函数是用来合并2个协程的

先来看看 foldCopies的参数

  • coroutineContext // 可以看出,此时coroutineContext为JobImpl 我们稍后来看看它是在什么时候赋值的
  • context // 默认什么都没有传,是 EmptyCoroutineContext
  • true // isNewCoroutine 是否创建新的Coroutine

我们在创建CoroutineScope的时候,会对coroutineContext赋值

image-20230227135752795

我们在创建协程作用域的时候, 会初始化一个Job, Job的默认实现为JobImpl

好了,在回到 CoroutineScope.newCoroutineContext方法

image-20230227140733819

执行完foldCopies后,

我们知道此时返回结果combined = jobImpl,

最后当返回的时候 if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)

最终给他添加一个默认调度器 [Dispatchers.Default]

tips: ContinuationInterceptor 是协程拦截器, 下面会说,不要急

再次回到主线流程
image-20230227142255809

此时newContext = [JobImpl , Dispatchers.Default]

如果说,有子协程的情况下,newCoroutineContext 这个方法就会使用最新的coroutineContext, 例如这样:

image-20230227142733877

这都是 foldCopies 的功劳, foldCopies的细节就不看了,没意义 [比较烧脑,不想看]

再接着往下走:

image-20230227143116362

在聊协程启动模式的时候说过,coroutineStart一共有4中模式

  • DEFAULT
  • LAZY
  • UNDISPATCHED
  • ATOMIC // 实验中

此时会判断是否是懒加载模式, 很明显不是懒加载,所以会走 StandaloneCoroutine

StandaloneCoroutine 会通过 handleJobException 捕获一些异常.

比如说在JVM中使用Main线程的时候,会提示

Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used

在这里就能捕获到

image-20230227143623791

在继续往下看:

image-20230227144214390

接下来就是开启一个协程

这里通过kotlin 的特性重载操作符,直接去它类中找到对应的方法即可

因为此时 协程启动模式是DEFAULT,那么直接看:

block.startCoroutineCancellable(receiver, completion)

即可

在接着往下看

createCoroutineUnintercepted(receiver, completion) 函数 源码位置

这个函数需要去kotiln官网看,太深了,我没看,我找到了 提供给需要的人!

这里看看拦截的方法

image-20230227145413801

可以看出,此时就会分发 continuation

先来看看不写 ContinuationInterceptor 是什么效果

image-20230227150205851

这段代码写过无数次, 因为协程默认启动模式需要调度,所以协程体内的代码还没来得及执行,main函数就已经结束了

那么在来看看添加协程拦截器后有什么变化

image-20230227150346152

可以看出, 协程会立即执行,我猜测是拦截的过程中会立即触发恢复,所以才会有这样的效果, 可惜的是我没找到恢复的代码

跟随源码手动创建协程

刚才看源码的时候看到了这段代码

image-20230227151308197

开启一个协程的时候, 通过函数扩展 扩展了 startCoroutineCancellable

那么我们是否也可以尝试的写一写

这里有一个注意点:

我们并不能调用 startCoroutineCancellable因为它是内部方法,我们无法直接调用

image-20230227152931128

只能拿 createCoroutine 来代替

来看看我们的代码:

image-20230227155331085

这里我把范型都替换成了具体的值,否则的话看的更迷糊

data class TestBean(val message: String)
fun main() {
    fun test(receiver: TestBean, block: suspend TestBean.() -> String) {
            block.createCoroutine(receiver, object : Continuation<String> { // 创建协程
                override val context: CoroutineContext
                    get() = EmptyCoroutineContext

                override fun resumeWith(result: Result<String>) {// 当协程恢复的时候执行
                    println("resume:$result")
                }
            })
    }

    val bean = TestBean("测试数据")

    test(bean) {
        println("我是test内部方法${this}")
        "我是返回数据"
    }
}

代码都写完了,但是这里并没有任何结果!

没有结果是正常现象,因为我们只是创建了一个协程,默认是挂起状态, 只有恢复的时候才会执行代码

例如这样:

image-20230227155649646

如果你觉得这样很麻烦,也可以直接

将 createCoroutine 改为 startCoroutine

  • createCoroutine // 创建协程 [默认挂起]
  • startCoroutine // 直接开启一个协程

image-20230227160020862

那么我们自定义CoroutineContxt是否还起作用呢?

image-20230227162655105

这里的时候,我们通过Job#cancel() 可以发现,并没有取消协程,恢复代码还是继续执行了

这是因为当我们使用 launch{} 开启一个协程的时候, 系统帮我们维护了job的各种状态

这里很简单,我们自己维护job即可

image-20230227162907083

系统代码指定是没有这么简单,不过模拟一下就可以了,没必要太纠结

那如果是异常如何捕获呢?

image-20230227163443183

需要注意的是,通过 CoroutineExceptionHandler捕获异常,这里监听的是 resumeWith方法

image-20230227163857448

只需要再次向上throw一下即可

简单的

刚才我们介绍的是有receiver的 startCoroutine,还有一个没有receiver的

image-20230227164714391

直接来看代码:

image-20230227164845823

这段代码很简答, 只是创建一个普通的协程,并恢复, 当然也可以通过CoroutineContext来控制协程,上面已经提到了,这里就不重复了

有创建协程手动恢复,就有直接创建并恢复

image-20230227165108121

有receiver和没有receiver的区别也很明显, 那就是在suspend方法体中是否有receiver.

总结

本篇我们阅读了 CoroutineScope#launch{}

并学习了手动管理协程的4个方法:

  • (suspend R.() -> T).startCoroutine // 有receiver直接恢复协程

  • (suspend R.() -> T).createCoroutine // 有receiver创建协程,需要手动恢复

  • (suspend () -> T).startCoroutine // 没有receiver直接恢复协程

  • (suspend () -> T).createCoroutine // 没有receiver创建协程,需要手动恢复

这四胞胎说实话,是真没啥用,但就是得了解一下… 看的头疼:)

完整代码

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/375805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Bitlocker加密,与解除加密

引文&#xff1a;应为C盘空间不够用了&#xff0c;想着用U盘从新给C盘分下区。操作时才发现我系统里的磁盘都是Bitlocker加密的&#xff0c;分区工具操作不了磁盘&#xff0c;所以就找到一下方法来解决。1&#xff0c;先讲一下解除加密&#xff1a;直接点击 &#xff1a;设置-&…

python pandas 常用方法汇总

前言 一、pandas是什么&#xff1f; 二、使用步骤 1.引入库 2.处理时间序列数据 3.分组聚合&#xff08;groupby&#xff09; 3.1基本方法 3.2具体使用&#xff1a;如图包含三个字段&#xff0c;company、salary、age 总结 Pandas 最最常用函数罗列 Pandas 函数用法示…

软件测试2年半的我,谈谈自己的理解...

软件测试两年半的我&#xff0c;谈谈自己的理解从2020年7月毕业&#xff0c;就成为一名测试仔。日子混了一鲲年&#xff0c;感觉需要好好梳理一下自己的职业道路了&#xff0c;回顾与总结下吧。一、测试的定位做事嘛&#xff0c;搞清楚自己的定位很重要。要搞清楚自己的定位&am…

新手小白根据Forexclub6点建议就能选择到最佳外汇经纪商

选择外汇经纪商很重要&#xff0c;尤其是对于外汇交易者新手而言。 在确定您计划使用的外汇交易员之前&#xff0c;Forexclub建议考虑以下6个因素产品丰富即使在这个阶段&#xff0c;您只对外汇交易感兴趣&#xff0c;拥有期权也是件好事。 大多数外汇经纪商提供对其他金融资产…

Excel工作表不能移动或复制?看看是不是这两个原因

Excel工作表不能移动或复制&#xff1f;今天来看看如何解决。 大家都知道&#xff0c;Excel表格分为工作簿和工作表&#xff0c;工作簿就是整个Excel文件&#xff1b;工作簿里面&#xff0c;也就是Excel表可以有多个工作表。 而各个工作表之间是可以相互移动或复制的&#xf…

C++赋值运算符重载

赋值运算符重载 目录赋值运算符重载示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;示例4&#xff1a;很巧妙的是&#xff0c;在编写这篇文章时&#xff08;2023年2月27日&#xff09;&#xff0c;再加100天就是6月7日&#xff0c;恰好是今年高考的百日誓师&#xff01; …

蓝库云|什么是供应链管理?SCM对制造业的重要性

企业在产品的销售经营上&#xff0c;往往不会考量到供应链管理(SCM)的流程规划&#xff0c;但现今的商业环境与以往不同&#xff0c;高度竞争与客户不断提升的期望&#xff0c;藉由做好供应链管理(SCM)&#xff0c;才能更准时的提供优质产品与优良服务&#xff0c;增强企业竞争…

HTML、CSS学习笔记4(3D转换、动画)

目录 一、空间转换&#xff08;3D转换&#xff09; 1.空间位移 语法&#xff1a; 取值&#xff1a;&#xff08;正负均可&#xff09; 透视&#xff1a; 2.空间旋转 3.立体呈现 二、动画&#xff08;animation&#xff09; 1.动画的使用 先定义动画 再调用定义好的动画 …

YSYY科研试剂DSPE-PEG-Cholesterol;磷脂聚乙二醇胆固醇简介;DSPE-PEG-胆固醇

二硬脂酰磷脂酰乙酰胺-聚乙二醇-胆固醇,DSPE-PEG-CLS&#xff0c;DSPE-PEG-Cholesterol 结构式&#xff1a; 中文名称&#xff1a;二硬脂酰磷脂酰乙酰胺-聚乙二醇-胆固醇英文名称&#xff1a;1,2-distearoyl-sn-glycero-3-phosphoethanolamine-N-[ Cholesterol(polyethylene g…

消息队列介绍和RabbitMQ的安装

1.消息队列 1.1 MQ的相关概念 1.1.1 什么是MQ MQ(message queue)&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO 先入先出&#xff0c;只不过队列中存放的内容是message 而已&#xff0c;还是一种跨进程的通信机制&#xff0c;用于上下游传递消息。在…

视频营销活动中7个常见的错误

如今&#xff0c;越来越多的企业在社交媒体平台上开展视频营销活动。与其他传统营销策略不同&#xff0c;视频营销可以为企业带来更多的销售机会。随着越来越多的视频社交媒体平台的出现&#xff0c;营销人员更应该抓住这个机会。但在开始视频创作之前&#xff0c;您需要有一个…

一次查询的全过程

一次查询的全过程&#xff1a; 比方说我这里有一个订单系统&#xff0c;一条查询请求发送过来&#xff0c;它内部是怎么执行的呢&#xff1f; 用户发送请求到业务系统&#xff0c;就会有一条线程来处理这个请求该线程会在数据库连接池里面获取一个JDBC连接MySQL工作线程会监听数…

从零开始的python基础教程(3)

十、Popular Python Packages 1、What are APIs Application Programming Interface 2、Search for Business 3、Hiding API Keys so now when we push our codes to Github repository, our config file will not be there 十一、使用Dyjango构建Web应用程序 1、Your Firs…

九年时间,倾情投入,JumpServer开源堡垒机v3.0正式发布

2023年2月27日&#xff0c;JumpServer开源堡垒机正式发布v3.0版本。在JumpServer开源堡垒机v3.0版本的设计过程中&#xff0c;我们始终秉持着“内外兼修”的原则&#xff0c;旨在进一步提升用户的使用体验&#xff0c;真正用心做好一款开源堡垒机。 在JumpServer v3.0版本中&…

回溯算法(BackTracking)

在许多情况下&#xff0c;回溯算法相当于穷举搜索的巧妙实现。回溯算法的一个具体例子是在新房子里摆放家具&#xff0c;开始什么也不摆放&#xff0c;然后每件家具被摆放在房间的某个位置&#xff0c;如果所有的家具都被摆放得令户主满意&#xff0c;那么算法终止&#xff1b;…

SpringMVC——响应处理(1)【包含源码分析】

Controller public class JsonReturnController {ResponseBodyGetMapping("/getPet")public Pet getPet(){Pet petnew Pet();pet.setAge(5);pet.setName("lily");return pet;} }项目启动后 浏览器输入 http://localhost:8080/getPet 。 debug DispatcherS…

十、vben框架如何使用table来写报表

在项目开发的过程中&#xff0c;有很多特殊的table样式&#xff0c;有的时候后端会用帆软来写报表&#xff0c;但是有的特殊的报表后端就不能支持实现了&#xff0c;那么前端是如何实现的呢&#xff0c;今天我们就来讲讲。 先上效果图&#xff1a; 本次使用的tsx组件来写的报表…

csapp第一章 --- 计算机系统漫游

重要内容大纲 1.1 C程序实现过程 一个由用户编写的“hello world”源代码到可以在屏幕上看见可执行文件经过一下过程&#xff1a; C语言翻译的阶段介绍 1.预处理cpp&#xff1a;头文件展开、宏定义替换 将 .c 文件&#xff08;源程序&#xff09;变成 .i 文件&#xff08;修改…

一文搞懂如何在 React 中使用 防抖(Debounce)和 节流(Throttle)

在前端的日常开发中&#xff0c;经常会使用到两个函数防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;&#xff0c;防抖函数可以有效控制在一段时间内只执行最后一次请求&#xff0c;例如搜索框输入时&#xff0c;只在输入完成后才进行请求接口。…

linux环境下打包c++的Qt应用程序装载vtk和itk

文章目录一、QT安装安装前准备1.1 方法一 源码编译安装(实践缺少xcb依赖)&#xff1a;1.2 方法二 run文件安装&#xff1a;二、迁移windows下qt应用到linux三、VTK安装3.1 安装ccmake 和 VTK 的依赖项3.2 linux下VTK库下载安装四、QT应用基础上引入VTK依赖五、ITK安装六、QT应用…