1.讲解异常之前先写这样一个例子
需求异步操作获取用户,主界面展示用户信息,怎么样用协程的方式去写
typealias CallBack=(User)->Unit
fun getUser(callback: CallBack){
thread {
log(1)
var user=User("he",23)
callback.invoke(user)
}
}
suspend fun getUserCoroutine()= suspendCoroutine<User> {
continuation->
getUser {
continuation.resume(it)
}
}
suspend fun main(){
GlobalScope.launch (Dispatchers.Main){
val name = getUserCoroutine().name
val age = getUserCoroutine().age
log(name+age)
}.join()
}
思考如果获取user的过程中有异常出现怎么处理,比如name为空字符串的user视为异常
interface MyCallBack<T>{
fun onSuccess(value:T)
fun onError(t:Throwable)
}
fun getUserWithError(callback: MyCallBack<User>){
//模拟异步操作
thread {
log(1)
var user=User("",23)
if (user.name.isEmpty()){
callback.onError(Throwable("姓名为空"))
}else{
callback.onSuccess(user)
}
}
}
suspend fun getUserCoroutineWithError()= suspendCoroutine<User> {
continuation->
getUserWithError(object :MyCallBack<User>{
override fun onSuccess(value: User) {
continuation.resume(value)
}
override fun onError(t: Throwable) {
continuation.resumeWithException(t)
}
})
}
suspend fun main(){
GlobalScope.launch {
try {
val user = getUserCoroutineWithError()
log(user.name)
}catch (t:Throwable){
log(t)
}
}.join()
}
从上面的代码我们可以看出一个异步的请求异常,我们只需要在协程里面try,catch就可以了
这个时候我们再去看开篇协程实现retrofit请求,就理解为什么可以这样子写
GlobalScope.launch {
try {
val weatherEntity = apiService.getMessage3("郑州")
println(weatherEntity.temperature)
}catch (e:Throwable){
println(e.message)
}
}
还有一种异常捕获方式,不需要写try,catch
suspend fun main(){
val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
log(throwable)
}
GlobalScope.launch(coroutineExceptionHandler) {
val user = getUserCoroutineWithError()
log(user.name)
}.join()
}
CoroutineExceptionHandler 同样也是协程上下文,但是不适用于async启动的协程