一、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的更多相关文章

  1. Kotlin 协程一 —— 全面了解 Kotlin 协程

    一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...

  2. Kotlin协程解析系列(上):协程调度与挂起

    vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...

  3. Android Kotlin协程入门

    Android官方推荐使用协程来处理异步问题.以下是协程的特点: 轻量:单个线程上可运行多个协程.协程支持挂起,不会使正在运行协程的线程阻塞.挂起比阻塞节省内存,且支持多个并行操作. 内存泄漏更少:使 ...

  4. rxjava回调地狱-kotlin协程来帮忙

    本文探讨的是在tomcat服务端接口编程中, 异步servlet场景下( 参考我另外一个文章),用rxjava来改造接口为全流程异步方式 好处不用说 tomcat的worker线程利用率大幅提高,接口 ...

  5. Kotlin协程第一个示例剖析及Kotlin线程使用技巧

    Kotlin协程第一个示例剖析: 上一次https://www.cnblogs.com/webor2006/p/11712521.html已经对Kotlin中的协程有了理论化的了解了,这次则用代码来直 ...

  6. Retrofit使用Kotlin协程发送请求

    Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...

  7. Kotlin协程基础

    开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...

  8. Kotlin协程通信机制: Channel

    Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间 ...

  9. Kotlin协程作用域与Job详解

    Job详解: 在上一次https://www.cnblogs.com/webor2006/p/11725866.html中抛出了一个问题: 所以咱们将delay去掉,需要改造一下,先把主线程的dela ...

  10. Kotlin协程作用域与构建器详解

    在上次我们是通过了这种方式来创建了一个协程: 接着再来看另一种创建协程的方式: 下面用它来实现上一次程序一样的效果,先来回顾一下上一次程序的代码: 好,下面改用runBlocking的方式: 运行一下 ...

随机推荐

  1. gpedit.msc 打不开

    win10系统推出已有不短的时间了,朋友们也纷纷升级了win10系统,但是暴露的问题也是越来越多,比如win10系统打开运行输入gpedit.msc命令时却提示找不到文件.那出现win10打不开gpe ...

  2. 【一文搞定】Linux、Mac、Windows安装Docker与配置教程!

    目录 一.Windows 安装 1.1 安装与启用 Hyper-V 1.2 安装 WSL 1.3 Docker Desktop 官方下载 1.4 安装Docker Desktop 二.MacOS 安装 ...

  3. [3] 以逆向的角度来看循环语句——do、while、for的比较

    [3] 以逆向的角度来看循环语句--do.while.for的比较 1. do循环 ​ 先执行循环体,后比较判断 #include <stdio.h> int main(int argc, ...

  4. github 2fa中国认证及TOTP App

    Because of your contributions on GitHub, two-factor authentication will be required for your account ...

  5. C++ Boost库 实现命令行解析

    Boost库中默认自带了一个功能强大的命令行参数解析器,以往我都是自己实现参数解析的,今天偶尔发现这个好东西,就来总结一下参数解析的基本用法,该库需要引入program_options.hpp头文件, ...

  6. Python 原生Socket实现端口扫描

    端口扫描,就是逐个对一段端口或指定的端口进行扫描.通过扫描结果可以知道一台计算机上都提供了哪些服务,Python中使用Socket即可实现对特定端口的探测,以及对C段的扫描. 扫描目标主机Banner ...

  7. Java执行Shell和传输文件

    特性: 多线程批量执行 多密码尝试 引入依赖: <dependency> <groupId>ch.ethz.ganymed</groupId> <artifa ...

  8. TP5发送短信限制

    <?php //发送手机验证码 function smsCode() { //dump($this->request->post()); //请求方式验证 /*if (!$this- ...

  9. uni-app+vue3会遇到哪些问题

    已经用 uni-app+vue3+ts 开发了一段时间,记录一下日常遇见的问题和解决办法 uni-app 中的单端代码 uni-app 是支持多端,如果你想让你的代码,只在部分平台使用,那么就需要用的 ...

  10. Git操作--Pycharm

    声明: 1)仅作为个人学习,如有冒犯,告知速删! 2)不想误导,如有错误,不吝指教! 一--在idea中配置git: 1. 更改git的安装路径:file-->settings,找到versio ...