| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> kotlin 协程异常处理机制颠覆三观 -> 正文阅读 |
|
[移动开发]kotlin 协程异常处理机制颠覆三观 |
文章目录协程的异常处理与 OKhttp 、
RxJava 这些框架的处理方式都不太一样,因为异步代码的异常处理,往往是比较麻烦的,而到了同步化处理的协程框架下,异常就变得比较容易进行管理了。
要完全理解协程的异常,我们需要先理解协程的树形结构和结构化并发,在这基础上,就能很容易的理解协程是如果管理异常的了。 协程树与结构化并发在协程作用域中,可以创建一个协程,同时,一个协程中还可以继续创建协程,所以这就形成了一个树形结构。借助这样的树形结构,协程可以很容易的控制结构化并发,父协程可以控制子协程的生命周期,而子协程可以从父协程继承协程上下文。 在代码中,可以通过 协程作用域的cancel借助协程作用域的管理,我们可以轻松的控制该协程作用域下的所有协程,一旦取消一个协程作用域,那么这个协程作用域下的所有协程都将被取消。
如上所示,调用 而如果只想取消某个单独的协程,那么可以通过该协程的句柄
如上所示,这样就只取消了 这就是协程结构化并发的两个特点:
在Android开发中,大部分场景下我们不需要考虑协程的 协程的cancel状态协程的 cancel 与线程的 cancel 类似,协程一旦开始执行(代码占用CPU),只有执行完毕才会被 cancel,当协程调用 cancel,只是将协程的Job 生命周期设置为了 Canceling,直到协程执行完毕才会被置为 Canceled 。 如果一定要及时取消掉协程的执行,那么可以和线程做类似的操作,在协程代码内及时判断协程的状态来控制代码的执行。 所以,协程推荐开发者在使用协程时,以协作的方式来使用,即随时判断当前协程的生命周期,避免浪费计算资源。 协程提供了两种方式来进行协作式的
清理通常, 当协程被取消时, 需要做一些清理工作, 此时, 可以把协程中运行的代码用
协程的返回值协程获取返回值有两种方式:
如果在调用Join后再调用cancel,那么协程将在执行完成后被Cancel,如果先cancel再调用Join,那么协程也将执行完成 协程异常的处理当协程作用域中的一个协程发生异常时,此时的异常流程如下所示:
这种行为实际上是符合协程结构化并发的规则的,但是在实际使用中,这种结构化的异常处理,会让异常的处理有些暴力,大部分场景下,业务需求都是希望异常不影响正常的业务流程。 结构化并发的异常处理所以,协程提出了
但是要注意的是,不论是SupervisorJob还是Job,如果协程内部发生异常,这个异常是肯定会被抛出的,只是是否会崩溃。 这里有个误区,那就是大家不要以为使用
使用Job的时候,第二个协程是无法执行的,但你改为SupervisorJob()之后,第二个协程就可以执行了,因为第一个协程的崩溃,并没有影响到第二个协程的执行。 所以说,SupervisorJob的目的是为了在结构化并发中找到一个特殊处理的方式,并没有将异常隐藏起来。
平时常见的MainScope,就是使用的SupervisorJob,所以MainScope中的子协程之间互相不会影响。 协程的异常处理前面我们说了,协程中的异常是一定会抛出的,所以在一个协程内部,我们到底怎么处理异常呢? launch:通过launch启动的异常可以通过try catch来进行异常捕获,或者使用协程封装的拓展函数runCatching来捕获,其内部也是使用的try catch。 async:async的异常处理比较麻烦,我们下面详细的说下。 首先,当async被用作构建根协程(由协程作用域直接管理的协程)时,异常不会主动抛出,而是在调用.await()时抛出。 来看下这个例子:
执行这个例子后,异常将被捕获,从上面的代码可以看出,异常只会发生在执行await的时候,调用async是不会发生异常的,不过,细心的朋友可能发现了,这里使用的是supervisorScope,如果我们改成coroutineScope呢? 执行代码后我们会发现,异常并没有被捕获,这就是我们前面说到的SupervisorJob和Job的区别。 再看一个例子:
我们去掉了supervisorScope,所以async的父协程是Job,所以这个时候,即使是调用async,也会发生异常,同时也不会被捕获。 综上,async的异常,只能在supervisorScope中,使用try catch进行捕获。 CoroutineExceptionHandler
我们来看下面的这个例子,在父协程中设置CoroutineExceptionHandler,当它的子协程发生异常时,即使不使用try catch,异常也会被捕获。
但是考虑下这样一个场景,让发生异常的协程使用CoroutineExceptionHandler,代码如下所示。
很遗憾,这样就不能捕获异常,因为 CoroutineExceptionHandler 属于异常抛出的协程,它本身无法处理。 所以,CoroutineExceptionHandler 的使用也有这样的限制,即CoroutineExceptionHandler 必须在发生异常的父协程中设置,其原因就是协程的结构化并发,异常会传递到父协程中进行处理,所以,这里必须是父协程中设置 CoroutineExceptionHandler 才能生效。 要注意的是, 实战一:停不下来的协程
发现取消协程后,日志还在疯狂输出,根本没有停下来。 实战二:可以停下来的协程
取消协程后,日志停止输出。 或者用 ensureActive() ,也可以达到同样的效果:
|
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:25:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |