kotlon协程,深入理解kotlin协程pdf,一文彻底搞懂Kotlin中的协程

kotlon协程,深入理解kotlin协程pdf,一文彻底搞懂Kotlin中的协程

本文主要介绍Kotlin协作流程的相关信息,通过示例代码进行了详细介绍。对大家的学习或工作都有一定的参考价值。有需要的朋友下面跟边肖学习。

生成背景

为了解决异步线程引起的回调问题

//传统回调方法

api.login(电话,psd)。enquene(new CallbackUser(){

公共void onSuccess(用户user){

api.submitAddress(地址)。enquene(new CallbackResult(){

public void on success(Result Result){

.

}

});

}

});

//使用协同流程后

val user=api.login(电话、psd)

提交地址(地址)

.

什么是协成?

本质上,协程是一个轻量级线程。

协同学的关键术语

val job=GlobalScope.launch {

延迟(1000)

println('世界世界!')

}

协同作用范围

控制线程、生命周期等。协程代码块执行,包括GlobeScope、lifecycleScope、viewModelScope和其他定制的协程作用域。

GlobeScope:全局范围,执行不会自动结束。

LifecycleScope:生命周期范围,用于具有生命周期的组件,如activity。销毁了会自动结束,所以需要另外引入。

ViewModelScope:ViewModel中使用的viewModel作用域,在viewModel回收时会自动结束,所以需要另外引入。

工作(工作)

流程的度量单位,相当于一个作业任务,默认情况下launch方法返回一个新作业。

suspend(挂起)

作用于一个方法意味着它是一个耗时的任务,比如上面的延迟方法。

公共暂停资金延迟(时间毫秒:长){

.

}

协同过程介绍

主框架($coroutines_version替换为最新版本,如1.3.9,下同)

实现' org . jetbrains . kot linx:kot linx-coroutines-core:$ coroutines _ version '

生命周期范围(可选,版本2.2.0)

实现“androidx . activity:activity-ktx:$ life cycle _ scope _ version”

ViewModelScope(可选,版本2.3.0-beta01)

实现“Android x . life cycle:life cycle-viewmodel-ktx:$ coroutines _ viewmodel _ version”

简单使用

我举个简单的例子。

lifecycleScope.launch {

延迟(2000年)

tvTest.text='Test '

}

上面例子的作用是等待2秒,然后将id为tvTest的TextView控件的文本值改为Test。

自定义延迟返回方法

在kotlin中,需要延迟返回结果的方法需要用suspend标记。

lifecycleScope.launch {

val text=getText()

tvTest.text=文本

}

suspend fun getText():String{

延迟(2000年)

返回“getText”

}

在其他线程中,如果需要使用Continuation来切换线程,可以用suspendCancellableCoroutine或suspendCoroutine(前者可以取消,相当于后者的扩展)包装,成功调用它. resume(),失败调用它. resumewithException (exception()),抛出异常。

suspend fun getTextInOtherThread()=suspendencellablecoroutinestring {

线程{

线程.睡眠(2000年)

it.resume('getText ')

}

}

异常捕获

协同流程中的故障可以通过异常捕获以统一的方式处理。

lifecycleScope.launch {

尝试{

val text=getText()

tvTest.text=文本

} catch (e:Exception){

e.printStackTrace()

}

}

取消功能

执行下面两个作业,第一个是原创,第二个是1秒后取消第一个作业,会导致tvText的文本不变。

val job=lifecycleScope.launch {

尝试{

val text=getText()

tvTest.text=文本

} catch (e:Exception){

e.printStackTrace()

}

}

lifecycleScope.launch {

延迟(1000)

job.cancel()

}

设置超时

这相当于系统封装了自动取消功能,对应withTimeout的功能。

lifecycleScope.launch {

尝试{

withTimeout(1000) {

val text=getText()

tvTest.text=文本

}

} catch (e:Exception){

e.printStackTrace()

}

}

带返回值的Job

和launch类似,还有一个异步方法,会返回一个延期对象,属于Job的扩展类。延期可以得到返回的结果,其具体用法如下

lifecycleScope.launch {

val one=async {

延迟(1000)

返回@异步1

}

val 2=async {

延迟(2000年)

返回@异步2

}

Log.i('scope test ',(one.await() two.await())。toString())

}

高级高级

自定义CoroutineScope

先看验光仪源码

公共接口协同作用域{

公共值协同上下文:协同上下文

}

验光仪中主要包含一个协同上下文对象,我们要自定义只需实现协同上下文的得到方法

类测试范围():协程范围{

重写赋值协程上下文:协程上下文

get()=TODO('尚未实现)

}

要创建协同上下文,得要先知道协同上下文是什么,我们再看协同上下文源码

/**

*协程的持久上下文。它是[元素]实例的索引集。

*索引集是集和映射的混合。

*该集合中的每个元素都有一个唯一的[键]。

*/

公共接口协同上下文{

公共运算符趣味E:元素get(key: KeyE): E?

公共基金R fold(初始:R,运算:(R,元素)- R): R

公共运算符fun plus(上下文:CoroutineContext):CoroutineContext=

.

公共基金减键(键:键*):协程上下文

公共接口KeyE:元素

公共接口元素:CoroutineContext {

.

}

}

通过注释说明,我们知道它本质就是一个包含元素的集合,只是不像设置和地图集合一样,它自己实现了获取(get),折叠(折叠,添加和替换的组合),相减(minusKey,移除),对象组合(另外,如val coroutine context=coroutine context 1 coroutine context 2)

它的主要内容是元素,而元素的实现有

职位任务

延续拦截器拦截器

AbstractCoroutineContextElement

CoroutineExceptionHandler

ThreadContextElement

downstreameexceptionelement

.

可以看到很多地方都有实现元素,它主要目的是限制范围以及异常的处理。这里我们先了解两个重要的元素,一个是工作,一个是协同调度程序

职位

工作:子职位取消,会导致父工作和其他子工作被取消;父工作取消,所有子工作被取消

主管工作:父工作取消,所有子工作被取消

协同调度程序

调度员。主要:主线程执行

调度员。木卫一线程执行

我们模拟一个类似生命周期范围的自定义测试范围

类测试范围():协程范围{

重写赋值协程上下文:协程上下文

get()=SupervisorJob()调度程序。主要的

}

这里我们定义了一个总流程线主管工作()以及具体执行环境调度员。主界面(安卓主线程),假如我们想替换掉活动的生命周期范围,就需要在活动中创建实例

val testScope=TestScope()

然后在活动销毁的时候取消掉所有工作

覆盖fun onDestroy() {

testScope.cancel()

super.onDestroy()

}

其他使用方式同生命周期范围,如

testScope.launch{

val text=getText()

tvTest.text=文本

}

深入理解Job

验光仪中包含一个主工作,之后调用的发动或其他方法创建的工作都属于验光仪的子工作,每个工作都有属于自己的状态,其中包括isActive、isCompleted、isCancelled,以及一些基础操作开始()、取消()、加入(),具体的转换流程如下

我们先从创建工作开始,当调用发动的时候默认有三个参数协同上下文、协同启动以及代码块参数。

上下文:协同上下文的对象,默认为协同启动。默认,会与验光仪的语境进行折叠

开始:协同启动的对象,默认为协同启动。默认,代表立即执行,同时还有协同启动。懒惰,代表非立即执行,必须调用工作的开始()才会开始执行

val作业2=生命周期范围。启动(start=CoroutineStart .懒惰){

延迟(2000年)

Log.i('范围测试','惰性)

}

job2.start()

当使用这种模式创建时默认就是新的状态,此时isActive、isCompleted、isCancelled都为假的,当调用开始后,转换为活跃的状态,其中只有isActive为没错,如果它的任务完成了则会进入完成状态,此时为等待子工作完成,这种状态下还是只有isActive为没错,如果所有子工作也完成了则会进入完成状态,只有已完成为没错。如果在活跃的或完成状态下出现取消或异常,则会进入消除状态,如果需要取消父工作和其他子工作则会等待它们取消完成,此时只有取消为没错,取消完成后最终进入取消状态,已取消和已完成都为真实的

状态

isActive

已完成

取消

新的

错误的

错误的

错误的

活跃的

真实的

错误的

错误的

完成

真实的

错误的

错误的

消除

错误的

错误的

真实的

取消

错误的

真实的

真实的

完成

错误的

真实的

错误的

不同工作交互需使用加入()与cancelAndJoin()

加入():将当前工作添加到其他协程任务里面

cancelAndJoin():取消操作,只是添加进去后再取消

val job 1=全局范围。启动(start=CoroutineStart .懒惰){

延迟(2000年)

Log.i('范围测试','作业1 ')

}

lifecycleScope.launch {

job1.join()

延迟(2000年)

Log.i('范围测试','作业2 ')

}

深入理解suspend

暂停作为科特林新增的方法修饰词,最终实现还是java,我们先看它们的差异性

暂停趣味测试1(){}

趣味测试2(){}

对应Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)代码

公共最终对象test1(@ not null Continuation $ completion){

返回单位。实例;

}

公共最终void test2() {

}

对应字节码

公共最终测试1(Lkotlin/协程/延续;)Ljava/lang/Object;

.

劳拉西泮

第610行

GETSTATIC kotlin/Unit .实例:Lkotlin/单位;

阿雷特纳

腰神经2

本地变量this Lcom/lieni/Android _ c/ui/test/test activity;L1 0

局部变量$ completion Lkotlin/协程/Continuation;L0 L1 1

MAXSTACK=1

MAXLOCALS=2

公开最终测试2()伏

劳拉西泮

9号线劳拉西泮

返回

腰神经2

本地变量this Lcom/lieni/Android _ c/ui/test/test activity;L1 0

MAXSTACK=0

MAXLOCALS=1

可以看到,加了暂停的方法其实和普通方法一样,只是传入时多了个继续对象,并返回了单位。情况对象

公共接口延续

公共值上下文:协同上下文

公共资金resumeWith(结果:ResultT)

}

而继续的具体实现在baseecontinuationimpl中

内部抽象类基础延续Impl(.):ContinuationAny?协程堆栈帧,可序列化{

公共最终覆盖有趣的简历(结果:ResultAny?) {

.

while (true) {

.

带有(当前){

val outcome=invokeSuspend(param)

.

releaseIntercepted()

如果(完成是basedicontinuationimpl){

.

}否则{

.

返回

}

}

}

}

.

}

当我们调用用.恢复时,它会一直执行一个循环,调用invokeSuspend(参数)和releaseIntercepted(),直到最顶层完成执行完成后返回,并且释放协程的拦截机

最终的释放在延续实施中实现

内部抽象类ContinuationImpl(.):BaseContinuationImpl(完成){

.

受保护的覆盖资金释放拦截(){

英国压力单位截取=截取

如果(拦截!=空截获!==这){

上下文[ContinuationInterceptor]!releaseInterceptedContinuation(已截获)

}

这个。截取=完成延续

}

}

通过这里知释放最终通过协同上下文中为延续拦截器的元素来实现

而暂停也是同理,继续看suspendCoroutine

public suspend inline fun T suspend coroutine(cross inline block:(continuation T)-Unit):T=

suspendcorouteininterceptedorreturn { c:continuation t-

val safe=安全延续(c . intercepted())

.

}

默认会调用继续的已截获()方法

内部抽象类ContinuationImpl(.):BaseContinuationImpl(完成){

.

公共基金拦截():ContinuationAny?=截取

?(context[延续拦截器]?截取延续(这个)?这个)。也{截取=它}

}

可以看到暂停最终也是通过协同上下文中为延续拦截器的元素来实现

流程总结(线程切换)

创建新的继续

调用验光仪中的语境的延续拦截器的中断延续方法暂停父任务

执行子任务(如果指定了线程,则在新线程执行,并传入继续对象)

执行完毕后用户调用继续的简历或者用.恢复返回结果

调用验光仪中的语境的延续拦截器的releaseInterceptedContinuation方法恢复父任务

阻塞与非阻塞

验光仪默认是不会阻塞当前线程的,如果需要阻塞可以使用运行阻塞,如果在主线程执行下面代码,会出现2s白屏

运行阻塞{

延迟(2000年)

Log.i('范围测试','运行阻塞已完成)

}

阻塞原理:执行运行阻塞默认会创建封锁路线,而封锁路线中会一直执行一个循环,直到当前职位为已完成状态才会跳出循环

公共基金运行阻塞(.):T {

.

val协程=阻塞协程(新上下文,当前线程,事件循环)

协程. start(协程启动.默认、协同程序、块)

返回协程. joinBlocking()

}

私有类BlockingCoroutineT(.):AbstractCoroutineT(父上下文,true) {

.

fun joinBlocking(): T {

.

while (true) {

.

如果(已完成)中断

.

}

.

}

}

总结

到此这篇关于一文彻底搞懂科特林中协程的文章就介绍到这了,更多相关科特林协程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • php读取pdf数据,php pdf读取
  • php读取pdf数据,php pdf读取,PHP中使用mpdf 导出PDF文件的实现方法
  • 深入解析C#(第4版),深入解析css pdf,深入解析contentWindow, contentDocument
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf,Java 反射机制原理与用法详解
  • ,,Java使用iTextPDF生成PDF文件的实现方法
  • ,,Python利用PyMuPDF实现PDF文件处理
  • 漫画算法小灰的算法之旅pdf,漫画算法2-小灰的算法进阶
  • devops和自动化运维实践 PDF,devops思想在运维方面的具体实践
  • pdf如何去除水印,pdf去水印的三种方法
  • 把a4的内容打印成a3小册子,a4的pdf文档如何打印成a3
  • nlp自然语言处理入门pdf,精通python自然语言处理 pdf
  • 容器docker基本操作,每天5分钟玩转docker容器技术 pdf
  • sklearn中文手册pdf下载,sklearn库模块及函数
  • ros机器人教程,ros机器人编程原理与应用下载 pdf 纽曼
  • 留言与评论(共有 条评论)
       
    验证码: