现在Android开发中运用异步一般都用上协程了,可是咱们怎么处理协程中的反常呢?
在谈协程处理反常方法之前,咱们先来说下协程中产生反常后会呈现什么状况.
当协程产生反常后
这儿分为两种
1,运用的协程Context是Job.
默许状况下创立协程Scope中的Context便是Job,
这种状况下一个Scope中的某个协程产生反常,这个Scope中的一切Child都会撤销,而且反常会向上传递。假如不希望某个子协程产生反常一切的协程都撤销的话就要用到SupervisorJob
2,运用的协程Context是SupervisorJob.
假如咱们创立CoroutineScope运用CoroutineScope(SupervisorJob()),那么它的子协程产生反常对别协程是没有影响的.
怎么处理协程的反常
发动协程有两种方法,一种launch另外一种的async. 这两种发动方法处理反常是有差异的。
运用try catch
当咱们运用launch创立协程的时分可以直接运用try catch去捕获反常
scope.launch {
try {
codeThatCanThrowExceptions()
} catch(e: Exception) {
// Handle exception
}
}
运用async的时分,try catch需求放在发动的时分调用(这儿调用await代表开始答应协程)
supervisorScope {
val deferred = async {
codeThatCanThrowExceptions()
} try {
deferred.await()
} catch(e: Exception) {
// 在这儿处理反常
}
}
留意这儿运用了supervisorScope,假如咱们运用coroutineScope,状况会有些不同
coroutineScope {
try {
val deferred = async {
codeThatCanThrowExceptions()
}
deferred.await()
} catch(e: Exception) {
// 这儿不会捕获反常,会传递反常到scope
}
}
至于这种状况咱们需求处理coroutineScope抛出的反常就要用到CoroutineExceptionHandler了.
运用CoroutineExceptionHandler
CoroutineExceptionHandler也是属于Coroutine Context中的一个元素,用于处理协程中抛出的未处理反常.
val handler = CoroutineExceptionHandler {
context, exception -> println("Caught $exception")
}
举个比如怎么运用它
val scope = CoroutineScope(Job())
scope.launch(handler) {
launch {
throw Exception("Failed coroutine")
}
}
留意CoroutineExceptionHandler必须要放在正确的方位才干捕获反常,例如放在如下的方位是不能捕获住反常的.
val scope = CoroutineScope(Job())
scope.launch {
launch(handler) {
throw Exception("Failed coroutine")
}
}
由于之前说到运用CoroutineScope中的反常是具有向上传递的. 除非咱们这儿换成SupervisorJob。
val scope = SupervisorJob(Job())
scope.launch {
launch(handler) {
throw Exception("Failed coroutine")
}
}
总结
一般咱们之前写程序过程中都是在运用try catch在捕获反常,可是当咱们运用协程后状况就有些不同,咱们要考虑反常的传递性,还需求考虑是否需求运用CoroutineExceptionHandler大局捕获协程中的反常