kotlin协程异常处理之-try catch
一、try catch
try catch是否一定有效呢?未必,来看一下:
1、withContext
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
println("launch start")
try {
withContext(Dispatchers.IO) {
// 可能抛出异常
}
} catch (ex: Exception) {
println("withContext caught: ${ex.message}")
}
println("launch end")
}
}
withContext是一个挂起函数,它会暂停当前协程的执行,等待传递进来的协程上下文切换后继续执行。当在withContext内部发生异常时,异常会被传递回到withContext函数的调用者,也就是当前协程的上一级代码中,进而可以被try-catch块捕获到。
2、launch
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
launch {
println("launch start")
// 可能抛出异常
println("launch end")
}
} catch (ex: Exception) {
println("launch caught: ${ex.message}")
}
}
try {
GlobalScope.launch {
throw NullPointerException()
}
} catch (e :Exception) {
e.printStackTrace()
}
launch启动的协程是独立于调用它的协程之外的一个新的协程,它没有直接的上级协程来捕获它的异常,因此try-catch在协程外部捕获不到协程中的异常。
事实证明,只要是launch的协程,无论是子协程还是根协程,都无法被捕获。比如:
GlobalScope.launch {
try {
launch {
Log.d("MainActivity_", "launch-> threadName->" + Thread.currentThread().name)
throw NullPointerException()
}
} catch (e :Exception) {
e.printStackTrace()
}
}
一样会崩溃。
如果将try catch放于内部:
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
try {
// 可能抛出异常
} catch (ex: Exception) {
println("launch caught: ${ex.message}")
}
println("launch end")
}
}
这样便可以捕获得到异常了。
3、async
(1)内部async
GlobalScope.launch {
try {
val deferredResult: Deferred<Int> = async {
Log.d("AsyncTest", "throw before")
throw Exception("async function exception")
Log.d("AsyncTest", "throw after")
}
deferredResult.await()
} catch (ex: Exception) {
Log.d("AsyncTest", "${ex.message}")
}
}
输出:
D/AsyncTest: throw before
D/AsyncTest: async function exception
但是程序奔溃了,可以捕获异常,但是会崩。
(2)、将try catch放于内部:
GlobalScope.launch {
val deferredResult: Deferred<Int> = async {
try {
Log.d("AsyncTest", "throw before")
throw Exception("async function exception")
Log.d("AsyncTest", "throw after")
} catch (e: java.lang.Exception) {
Log.d("AsyncTest", "${e.message}")
}
}
deferredResult.await()
}
输出:
D/AsyncTest: throw before
D/AsyncTest: async function exception
可以捕获异常,并且程序不会崩溃。
(3)、使用GlobalScope.async
GlobalScope.launch {
try {
val deferredResult: Deferred<Int> = GlobalScope.async {
Log.d("AsyncTest", "throw before")
throw Exception("async function exception")
Log.d("AsyncTest", "throw after")
}
deferredResult.await()
} catch (ex: Exception) {
Log.d("AsyncTest", "${ex.message}")
}
}
输出:
D/AsyncTest: throw before
D/AsyncTest: async function exception
可以捕获异常,并且程序不会崩溃。
(4)、只对deferredResult.await()try catch
GlobalScope.launch {
val deferredResult: Deferred<Int> = GlobalScope.async {
Log.d("AsyncTest", "throw before")
throw Exception("async function exception")
Log.d("AsyncTest", "throw after")
}
try {
deferredResult.await()
} catch (e: Exception) {
Log.d("AsyncTest", "${e.message}")
}
}
输出:
D/AsyncTest: throw before
D/AsyncTest: async function exception
可以捕获异常,并且程序不会崩溃。
结论
1、withContext是一个挂起函数,它会暂停当前协程的执行,等待传递进来的协程上下文切换后继续执行。当在withContext内部发生异常时,异常会被传递回到withContext函数的调用者,也就是当前协程的上一级代码中,进而可以被try-catch块捕获到。
2、launch启动的协程是独立于调用它的协程之外的一个新的协程,它没有直接的上级协程来捕获它的异常,因此try-catch在协程外部捕获不到协程中的异常。
3、async如果启动的是子协程,那么代码执行到 throw 异常的时候就抛出了异常,与是否调用await方法无关,这个异常可以用try-catch捕获但是会引起崩溃。
4、async开启一个根协程,在调用await方法时候会抛出异常,这个异常可以用try-catch捕获不引起崩溃。
kotlin协程异常处理之-try catch的更多相关文章
- Kotlin 协程一 —— 全面了解 Kotlin 协程
一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
- Android Kotlin协程入门
Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...
- rxjava回调地狱-kotlin协程来帮忙
本文探讨的是在tomcat服务端接口编程中, 异步servlet场景下( 参考我另外一个文章),用rxjava来改造接口为全流程异步方式 好处不用说 tomcat的worker线程利用率大幅提高,接口 ...
- Kotlin协程第一个示例剖析及Kotlin线程使用技巧
Kotlin协程第一个示例剖析: 上一次https://www.cnblogs.com/webor2006/p/11712521.html已经对Kotlin中的协程有了理论化的了解了,这次则用代码来直 ...
- Retrofit使用Kotlin协程发送请求
Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...
- Kotlin协程基础
开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...
- Kotlin协程通信机制: Channel
Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间 ...
- Kotlin协程作用域与Job详解
Job详解: 在上一次https://www.cnblogs.com/webor2006/p/11725866.html中抛出了一个问题: 所以咱们将delay去掉,需要改造一下,先把主线程的dela ...
- Kotlin协程作用域与构建器详解
在上次我们是通过了这种方式来创建了一个协程: 接着再来看另一种创建协程的方式: 下面用它来实现上一次程序一样的效果,先来回顾一下上一次程序的代码: 好,下面改用runBlocking的方式: 运行一下 ...
随机推荐
- 【分享笔记】druid存储系统-思维导图
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu 公众号:一本正经的瞎扯 源于:<Druid实时大数据分析原理与实践>这本书的阅读笔记 ...
- 【JS 逆向百例】37网游登录接口参数逆向
声明 本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:37网游登录 主页:https://www.37.co ...
- Go 泛型发展史与基本介绍
Go 泛型发展史与基本介绍 Go 1.18版本增加了对泛型的支持,泛型也是自 Go 语言开源以来所做的最大改变. 目录 Go 泛型发展史与基本介绍 一.为什么要加入泛型? 二.什么是泛型 三.泛型的来 ...
- PLC检测
填空题1 填空A-E 程序图一 第一训练题的程序,一个是用常开触点,一个是用上升沿指令,建议选上升沿指令编程 程序二 程序图三 程序四 程序五
- SqlSugar新增数据
1.插入方式 1.1 单条插入实体 //返回插入行数 db.Insertable(insertObj).ExecuteCommand(); //都是参数化实现 //异步: await db.Inser ...
- 【三】强化学习之PaddlePaddlle-Notebook、&pdb、ipdb 调试---及PARL框架
相关文章: [一]飞桨paddle[GPU.CPU]安装以及环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简 ...
- 从嘉手札<2023-11-20>
写给十年如一日的偶像--Faker "我看了一下,觉得视频还不够清晰,等我换一个清晰点的摄像头再回来直播,不要走开~" 繁星满天,流光飞逝. 世界是一场盛大的表演, 舞台上熙熙攘攘 ...
- Firefox浏览器的一些配置
一.在新标签页打开书签 1.打开Firefox浏览器,地址栏输入about:config. 2.选择"接受风险并继续". 3.搜索browser.tabs.loadBookmark ...
- 面试官:SpringCloudGateway过滤器类型有哪些?
在 Spring Cloud Gateway 中,过滤器是在请求到达目标服务之前或之后,执行某些特定操作的一种机制.例如,它可以实现对传入的请求进行验证.修改.日志记录.身份验证.流量控制等各种功能. ...
- 一次人脸识别ViewFaceCore使用的经验分享,看我把门店淘汰下来的POS机改成了人脸考勤机
POS软件是什么?你好意思吗,还在用老掉牙的Winform. 门店被淘汰的POS机 销售终端--POS(point of sale)是一种多功能终端,把它安装在信用卡的特约商户和受理网点中与计算机联成 ...