当前位置:网站首页>Exception handling in kotlin process
Exception handling in kotlin process
2022-07-03 02:07:00 【yu-Knight】
List of articles
The necessity of exception handling
- When something unexpected happens to the application , It is very important to provide users with the right experience , One side , It's a terrible experience to witness an application crash , On the other hand , When user operation fails , You must also be able to give correct prompt information .
Abnormal propagation
- There are two forms of coprocessor : Auto propagate exception (launch And actor), Expose exceptions to users (async And produce) When these builders are used to create a root collaboration ( This process is not a child of another process ), The former type of builder , An exception is thrown the first time it occurs , The latter relies on users to end up with abnormal consumption , For example, through await or receive.
@Test
fun `test exception propagation`() = runBlocking<Unit> {
val job = GlobalScope.launch {
try {
throw IndexOutOfBoundsException()
} catch (e: Exception) {
println("Caught IndexOutOfBoundsException")
}
}
job.join()
val deferred = GlobalScope.async {
throw ArithmeticException()
}
try {
deferred.await()
} catch (e: Exception) {
println("Caught ArithmeticException")
}
/** Caught IndexOutOfBoundsException Caught ArithmeticException */
}
Non root coroutine exception
- In the processes created by other processes , The generated exception will always be propagated .
@Test
fun `test exception propagation2`() = runBlocking<Unit> {
val scope = CoroutineScope(Job())
val job = scope.launch {
// If async Throw an exception ,launch Will immediately throw an exception , Instead of calling .await()
async {
throw IllegalArgumentException()
}
}
job.join()
}
Abnormal propagation characteristics
- When a coroutine fails due to an exception , It will propagate the exception and pass it to its parent . Next , The parent will perform the following operations :
- 1. Cancel its own children
- 2. Cancel itself
- 3. Propagate the exception and pass it to its parent

SupervisorJob
- Use SupervisorJob when , The failure of one subprocess will not affect other subprocesses .SupervisorJob Will not propagate exceptions to its parent , It lets the subroutine handle the exception itself .
- This requirement is common in defining jobs in scope UI Components , If any one UI The sub job execution of failed , It is not always necessary to cancel the whole UI Components , But if UI The components were destroyed , Because its result is no longer needed , It is necessary to make all sub jobs fail .
@Test
fun `test SupervisorJob`() = runBlocking<Unit> {
val supervisor = CoroutineScope(SupervisorJob())
val job1 = supervisor.launch {
delay(100)
println("child 1")
throw IllegalArgumentException()
}
val job2 = supervisor.launch {
try {
delay(Long.MAX_VALUE)
} finally {
println("child 2 finished")
}
}
delay(200)
supervisor.cancel()
joinAll(job1, job2)
}
supervisorScope
- When the execution of the job itself fails , All sub jobs will be cancelled
@Test
fun `test SupervisorScope`() = runBlocking<Unit> {
try {
supervisorScope {
val child = launch {
try {
println("The child is sleeping")
delay(Companion.MAX_VALUE)
} finally {
println("The child is cancelled")
}
}
yield()// Use yield Let's give our sub job a chance to print
println("Throwing an exception from the scope")
throw AssertionError()
}
} catch (e: AssertionError) {
println("Caught an assertion error")
}
/** The child is sleeping Throwing an exception from the scope The child is cancelled Caught an assertion erro */
}
Abnormal capture
- Use CoroutineExceptionHandler Catch the exception of the cooperation process .
- When the following conditions are met , The exception will be caught :
1. opportunity : An exception is thrown by a coroutine that automatically throws an exception ( Use launch, instead of async when );
2. Location : stay CoroutineScope Of CoroutineContext Or in a root coroutine (CoroutineScope perhaps supervisorScope Direct subprocess of ) in .
@Test
fun `test CoroutineExceptionHandler`() = runBlocking<Unit> {
val handler = CoroutineExceptionHandler {
_, exception ->
println("Caught $exception")
}
val job = GlobalScope.launch(handler) {
throw AssertionError() // Exception caught
}
val deferred = GlobalScope.async(handler) {
throw ArithmeticException() // Not captured
}
job.join()
deferred.await()
}
@Test
fun `test CoroutineExceptionHandler2`() = runBlocking<Unit> {
val handler = CoroutineExceptionHandler {
_, exception ->
println("Caught $exception")
}
val scope = CoroutineScope(Job())
// It can catch the exception thrown by the subprocess
val job = scope.launch(handler) {
launch {
throw AssertionError()// Throw an exception to the parent process
}
}
job.join()
}
Android Global exception handling in
- The global exception handler can get all unhandled exceptions of the collaboration , However, it cannot catch exceptions , Although it can't prevent the program from crashing , Global exception handlers are still very useful in scenarios such as program debugging and exception reporting .
- We need to be in classpath Create below META-INF/services Catalog , And create one of them called kotlinx.coroutines.CoroutineExceptionHandler The file of , The content of the file is the full class name of our global exception handler .
class GlobalCoroutineExceptionHandler : CoroutineExceptionHandler {
override val key = CoroutineExceptionHandler
override fun handleException(context: CoroutineContext, exception: Throwable) {
Log.d("yuknight", "Unhandled Coroutine Exception:$exception")
}
}
Cancel and exception
- Cancellation is closely related to exceptions , Used internally in the process CancellationException To cancel , This exception will be ignored .
- When the subprocess is cancelled , It will not cancel its parent process .
- If a collaboration encounters CancellationException An exception , It will use this exception to cancel its parent coroutine . When all the child processes of the parent process are finished , Exceptions will be handled by the parent coroutine .
@Test
fun `test cancel and exception`() = runBlocking<Unit> {
val job = launch {
val child = launch {
try {
try {
delay(Long.MAX_VALUE)
} catch (e: Exception) {
e.printStackTrace()
}
} finally {
println("Child is cancelled")
}
}
yield()
println("Cancelling child")
child.cancelAndJoin()
yield()
println("Parent is not cancelled")
}
job.join()
}
@Test
fun `test cancel and exception2`() = runBlocking<Unit> {
val handler = CoroutineExceptionHandler {
_, exception ->
println("Caught $exception")
}
val job = GlobalScope.launch(handler) {
launch {
try {
delay(Long.MAX_VALUE)
} finally {
withContext(NonCancellable) {
println("Children are cancelled, but exception is not handled until all children terminate")
delay(100)
println("The first child finished its non cancellable block")
}
}
}
launch {
delay(10)
println("Second child throws an exception")
throw ArithmeticException()
}
}
job.join()
/** Second child throws an exception Children are cancelled, but exception is not handled until all children terminate The first child finished its non cancellable block Caught java.lang.ArithmeticException */
}
Abnormal aggregation
- When multiple child processes of a process fail due to exceptions , Generally, the first exception is taken for processing . All other exceptions that occur after the first exception , Will be bound to the first exception .
@Test
fun `test exception aggregation`() = runBlocking<Unit> {
val handler = CoroutineExceptionHandler {
_, exception ->
println("Caught $exception ${
exception.suppressed.contentToString()}")
}
val job = GlobalScope.launch(handler) {
launch {
try {
delay(Long.MAX_VALUE)
} finally {
throw ArithmeticException()
}
}
launch {
try {
delay(Long.MAX_VALUE)
} finally {
throw IndexOutOfBoundsException()
}
}
launch {
delay(100)
throw IOException()
}
}
job.join()
/** Caught java.io.IOException [java.lang.ArithmeticException, java.lang.IndexOutOfBoundsException] */
}
边栏推荐
- Problems encountered in small program development of dark horse shopping mall
- Network security - talking about security threats
- Socket编程
- easyPOI
- easyExcel
- leetcode961. Find the elements repeated N times in the array with length 2n
- 转载收录6.5大侠写的部分Qt开发经验
- [shutter] shutter debugging (debugging fallback function | debug method of viewing variables in debugging | console information)
- His experience in choosing a startup company or a big Internet company may give you some inspiration
- 微信小程序开发工具 POST net::ERR_PROXY_CONNECTION_FAILED 代理问题
猜你喜欢

Technology sharing | Frida's powerful ability to realize hook functions

In the face of difficult SQL requirements, HQL is not afraid

Learn BeanShell before you dare to say you know JMeter

The testing process that software testers should know

MySQL learning 03

Stm32f407 ------- IIC communication protocol

elastic stack

Solution for processing overtime orders (Overtime unpaid)

What are MySQL locks and classifications
![[camera topic] how to save OTP data in user-defined nodes](/img/3e/b76c4d6ef9ab5f5b4326a3a8aa1c4f.png)
[camera topic] how to save OTP data in user-defined nodes
随机推荐
Network security - cracking system passwords
Storage basic operation
Analysis, use and extension of open source API gateway apisex
《上市风云》荐书——唯勇气最可贵
Everything file search tool
Socket编程
Introduce in detail how to communicate with Huawei cloud IOT through mqtt protocol
小程序開發的部分功能
Explore the conversion between PX pixels and Pt pounds, mm and MM
Network security - password cracking
Network security - virus
CFdiv2-Fixed Point Guessing-(區間答案二分)
Visual yolov5 format data set (labelme JSON file)
转载收录6.5大侠写的部分Qt开发经验
【Camera专题】手把手撸一份驱动 到 点亮Camera
详细些介绍如何通过MQTT协议和华为云物联网进行通信
In the face of difficult SQL requirements, HQL is not afraid
MySQL learning 03
去除网页滚动条方法以及内外边距
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance o