安卓开发封装处理Retrofit协程请求中的异常
上篇文章讲解了怎么使用Kotlin
的协程配合Retrofit
发起网络请求,使用也是非常方便,但是在处理请求异常还不是很人性化。这篇文章,我们将处理异常的代码进行封装,以便对异常情况返回给页面,提供更加友好的提示。
编写拓展方法
我们写一个扩展(全局)方法,就叫ViewModelExt.kt
,在下面创建方法。
/**
* ViewModel扩展方法:启动协程
* @param block 协程逻辑
* @param onError 错误回调方法
* @param onComplete 完成回调方法
*/
fun ViewModel.launch(
block: suspend CoroutineScope.() -> Unit,
onError: (e: Throwable) -> Unit = { _: Throwable -> },
onComplete: () -> Unit = {}
) {
viewModelScope.launch(
CoroutineExceptionHandler { _, throwable ->
run {
// 这里统一处理错误
ExceptionUtil.catchException(throwable)
onError(throwable)
}
}
) {
try {
block.invoke(this)
} finally {
onComplete()
}
}
}
统一异常处理
拓展方法里面对写成过程做了统一拦截,在onComplete
方法可以做统一的异常处理
/**
* 异常工具类
* @author ssq
*/
object ExceptionUtil {
/**
* 处理异常,toast提示错误信息
*/
fun catchException(e: Throwable) {
e.printStackTrace()
when (e) {
is HttpException -> {
catchHttpException(e.code())
}
is SocketTimeoutException -> {
showToast(R.string.common_error_net_time_out)
}
is UnknownHostException, is NetworkErrorException -> {
showToast(R.string.common_error_net)
}
is MalformedJsonException, is JsonSyntaxException -> {
showToast(R.string.common_error_server_json)
}
is InterruptedIOException -> {
showToast("服务器连接失败,请稍后重试")
}
// 自定义接口异常
is ApiException -> {
showToast(e.message?:"", e.code)
}
is ConnectException -> {
showToast( "连接服务器失败" )
}
else -> {
showToast("${MyApplication.instance.getString(
R.string.common_error_do_something_fail
)}:${e::class.java.name}")
}
}
}
/**
* 处理网络异常
*/
fun catchHttpException(errorCode: Int) {
if (errorCode in 200 until 300) return// 成功code则不处理
showToast(
catchHttpExceptionCode(
errorCode
), errorCode
)
}
/**
* toast提示
*/
private fun showToast(@StringRes errorMsg: Int, errorCode: Int = -1) {
showToast(
MyApplication.instance.getString(
errorMsg
), errorCode
)
}
/**
* toast提示
*/
private fun showToast(errorMsg: String, errorCode: Int = -1) {
if (errorCode == -1) {
ToastUtils.showShort(errorMsg)
} else {
ToastUtils.showShort("$errorCode:$errorMsg")
}
}
/**
* 处理网络异常
*/
private fun catchHttpExceptionCode(errorCode: Int): Int = when (errorCode) {
in 500..600 -> R.string.common_error_server
in 400 until 500 -> R.string.common_error_request
else -> R.string.common_error_request
}
}
ApiException
是自定义的异常类
如何使用
我们在一个ViewModel
中可以这样使用
fun login(user: User) = launch({
val resultData = RetrofitClient.userService.login(user)
if (resultData.code == 20000) {
userInfo.value = RetrofitClient.userService.getUserInfo().data
}
},onError = { e: Throwable ->
})
如果是返回的结果不对,可以这样做
fun login(user: User) = launch({
val resultData = RetrofitClient.userService.login(user)
if (resultData.code == 20000) {
userInfo.value = RetrofitClient.userService.getUserInfo().data
} else {
throw ApiException(-1, "返回结果出错")
}
},onError = { e: Throwable ->
})
ApiException
是自定义的异常处理
使用Demo:
上篇文章:使用Kotlin协程配合Retrofit发送请求
安卓开发封装处理Retrofit协程请求中的异常的更多相关文章
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- python 全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)
昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...
- 封装你的协程Unity TaskManager
unity5提供了协程,不过用起来很蛋疼,当然如果是unity2017 你就可以用async await了 提供一个TaskManager来封装协程(github https://github.co ...
- Python协程(中)
协程嵌套 使用async可以定义协程,协程用于耗时的io操作,我们也可以封装更多的io操作过程,这样就实现了嵌套的协程,即一个协程中await了另外一个协程,如此连接起来. import asynci ...
- 【Golang】如何统一处理HTTP请求中的异常捕获
最近写GOLANG项目,不使用框架,路由选择httprouter 现在想实现一个需求:在不修改httprouter源码的前提下,对所有注册的路由handle进行异常捕获. 大家都知道golang使用p ...
- [日常] 使用TCPDUMP和Ethereal抓包分析HTTP请求中的异常情况
在测试功能的过程中,出现这样一种现象.前端js发起ajax请求后,在浏览器的审查元素网络状态中可以看到status为pending,等15秒以后js会把当前超时的请求取消掉,变成了红色的cancel. ...
- Python全栈开发-Day10-进程/协程/异步IO/IO多路复用
本节内容 多进程multiprocessing 进程间的通讯 协程 论事件驱动与异步IO Select\Poll\Epoll——IO多路复用 1.多进程multiprocessing Python ...
- RxHttp ,比Retrofit 更优雅的协程体验
1.前言 Hello,各位小伙伴,又见面了,回首过去,RxHttp 就要迎来一周年生日了(19年4月推出),这一年,走过来真心....真心不容易,代码维护.写文章.写文档等等,经常都是干到零点之后,也 ...
- Python开发【第九章】:线程、进程和协程
一.线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 1.t ...
- Python开发基础-Day32 进程间通信、进程池、协程
进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...
随机推荐
- 全面的开发者文档和用户目标解析:API 文档指南和开发者旅程
开发者文档 开发者文档,也称为 API 文档,是一种专门针对软件开发人员的技术写作形式.这种类型的文档通常包括 API 的技术规范.代码注释.软件设计和架构以及软件开发中涉及的其他详细技术描述.开发者 ...
- Seaborn分布数据可视化---箱型分布图
箱型分布图 boxplot() sns.boxplot( x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient ...
- C# 使用GridControl显示数据库表格 使用VS2017连接Mysql并显示数据库表格
教程引用:https://www.bilibili.com/video/BV1pT4y1u7d2?from=search&seid=10645874367755405718
- 面试官:Redis如何实现延迟任务?
延迟任务(Delayed Task)是指在未来的某个时间点,执行相应的任务.也就是说,延迟任务是一种计划任务,它被安排在特定的时间后执行,而不是立即执行. 延迟任务的常见使用场景有以下几个: 定时发送 ...
- 编译安装openGauss 3.0.0
编译安装 openGauss 3.0.0 环境检查 1.1 检查 OS 版本 openGauss支持的操作系统: CentOS 7.6(x86 架构) openEuler-20.03-LTS(aarc ...
- nethttp和gin 路由
net/http 路由注册 func test1() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Requ ...
- 力扣239(Java)- 滑动窗口最大值(困难)
题目: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回 滑动窗口中的最大值 . 示 ...
- 同为博客,不同风格 ——Hexo另类搭建
简介:通过阿里云云开发平台快速由Hexo创建赛博朋克风格的博客. 一 .通过云开发平台快速创建初始化应用 1.创建相关应用模版请参考链接:Hexo博客框架-轻量.一令部署 2.完成创建后就可以在g ...
- 如何通过 Serverless 提高 Java 微服务治理效率?
简介: 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发.但是随着公司的发展,会不断往系统里面添加新的业务功能,系统越来越庞大,需求不断增加,越来越多的人也会加入到开发团队 ...
- 项目版本管理的最佳实践:云效飞流Flow篇
简介: 飞流Flow的最佳实践(使用阿里云云效)为了更好地使用飞流Flow,接下来将结合阿里云云效来讲解飞流Flow的最佳实践 目录 一.分支规约 二.版本号规约 2.1 主版本号(首位版本号) 2. ...