coroutineScope和supervisorScope都是用来创建一个CoroutineScope并执行代码块,区别在于coroutineScope的 coroutine是一个ScopeCoroutine,而supervisorScope的coroutine是一个SupervisorCoroutine。SupervisorCoroutine继承自ScopeCoroutine但是重写了其父类JobSupport的方法childCancelled(cause:Throwable):Boolean并返回false,这就是它们之间的唯一区别。
在coroutineScope中,只要任意一个子协程发生异常,整个scope都会执行失败,并且其余的所有子协程都会被取消而在supervisorScope中,一个子协程的异常不会影响整个scope的执行,也不会影响其余子协程的执行。
在supervisorScope的代码块中使用多条async执行异步请求,即便请求有异常其他请求依然会执行。一旦使用了async+awiat,请求发生异常还是会抛出异常结束其他请求,这里可以使用CoroutineExceptionHandler进行异常拦截。
想要达到多条请求并发并获取结果就需要对每条请求进行try-catch,异常中填入默认值或空值,这样就能达到需求。如需满足某个请求成功后才能继续其他请求可以使用invokeOnCompletion监听取消请求
val bean = MutableStateFlow(AllDataBean())
viewModelScope.launch(CoroutineExceptionHandler { _, throwable ->
Timber.e("接口异常handler:${throwable.message}")
}) {
supervisorScope {
val _data1 = async { getData1() }//请求1
val _data2 = async { getData2() }//请求2
val _data3 = async { getData3() }//请求3
val _data4 = async { getData4() }//请求4
// 当_data1请求抛异常时,取消_data2请求
_data1.invokeOnCompletion { throwable ->
throwable?.let { _data2.cancel() }
}
//调用了await后可能会抛异常,这里给默认值
val data1 = try {
_data1.await().data
} catch (e: Exception) {
Data1Bean()
}
val data2 = try {
_data2.await().data
} catch (e: Exception) {
Data2Bean()
}
val data3 = try {
_data3.await().data
} catch (e: Exception) {
mutableListOf<Data3Bean>()
}
val data4 = try {
_data4.await().data
} catch (e: Exception) {
Data4Bean()
}
val allDataBean =
AllDataBean(data1, data2, data3, data4)
bean.emit(allDataBean)
}
}