安卓开发封装处理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是自定义的异常处理

Original: https://www.cnblogs.com/sw-code/p/15591713.html
Author: sw-code
Title: 安卓开发封装处理Retrofit协程请求中的异常

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585576/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • redis的三种集群方式

    redis有三种集群方式:主从复制,哨兵模式和集群。 1.主从复制 主从复制原理: 从服务器连接主服务器,发送SYNC命令; 主服务器接收到SYNC命名后,开始执行BGSAVE命令…

    Linux 2023年5月28日
    087
  • lab 1

    int father[2],son[2]; int son[2]; if (fork() == 0) { int n; char buf[1]; close(0); dup(fat…

    Linux 2023年6月7日
    075
  • AOP+Redis+SpringCache翻译字典状态

    1,字典表Or枚举类? 项目里有很多标识状态的字段,比如订单状态:0-未支付,1-已支付,2-已取消。或者性别sex: 0-未知,1-男,2-女 。等等。一般这种我们都会建相应的枚…

    Linux 2023年5月28日
    0118
  • [python][flask] Jinja 模板入门

    1、快速体验 2、Flask 最小 DEMO 3、模板继承 4、Super Blocks 5、Macros 6、自定义过滤器 7、结论 参考链接 Flask 和 Django 附带…

    Linux 2023年6月8日
    096
  • 浪剑天下H5游戏详细图文架设教程

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    096
  • 一个老程序员的忠告:你这辈子输就输在以为靠技术就能生存下

    一、 在一个地方工作8小时就是”穷” 1、在中国你千万不要因为学习技术就可以换来稳定的生活和高的薪水待遇,你更不要认为那些从事市场开发,跑腿的人,没有前途。…

    Linux 2023年6月14日
    0126
  • 面试题目汇总

    目录: 1、数字数组数字数组2、字符串字符串3、链表 链表4、二叉树二叉树 5、堆栈 堆栈 posted @2019-12-11 20:35 风御之举 阅读(63 ) 评论() 编…

    Linux 2023年6月13日
    090
  • 备用链接

    win10 stick note 地址 https://www.partitionwizard.com/partitionmanager/where-are-sticky-note…

    Linux 2023年6月7日
    090
  • 剑指offer计划29(动态规划困难)—java

    1.1、题目1 剑指 Offer 19. 正则表达式匹配 1.2、解法 动态规划后面再研究 1.3、代码 class Solution { public boolean isMat…

    Linux 2023年6月11日
    0109
  • linux命令之tar 解压 压缩

    tar(全称:tape archive )命令用于备份文件。tar 是用来 创建或者 还原备份文件的工具程序,它可以加入,解开备份文件内的文件。tar linux说明 tar [&…

    Linux 2023年5月27日
    082
  • Python List 中的append 和 extend 的区别

    方法的参数不同 append 方法是向原list的末尾添加一个对象(任意对象;如元组,字典,列表等),且只占据一个原list的索引位,添加后无返回值,直接在原列表中添加。 list…

    Linux 2023年6月7日
    094
  • 部署apache

    1、使用DockerHub镜像 [root@master ~]# mkdir httpd_dockerfile [root@master ~]# cd httpd_dockerfi…

    Linux 2023年6月13日
    0115
  • 017 Linux 之啥是 ssh ?

    1 什么是 ssh?有什么用? (1)ssh 是一种协议 (2)ssh 服务 2 ssh 基于密匙的安全验证过程是怎样的? 3 对称加密与非对称加密区别是什么? (1)对称加密 (…

    Linux 2023年5月27日
    0118
  • 基于LNMP快速简单搭建wordpress平台

    一、WordPress 简介 WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把WordPress当…

    Linux 2023年6月7日
    0105
  • JAVA设计模式-工厂模式

    JAVA设计模式-工厂模式 简单工厂模式 介绍 简单工厂模式就是定义一个工厂类,工厂类提供获取实例的方法,方法会根据传入的参数不同来返回不同的实例。不同的实例基本都有共同的父类。对…

    Linux 2023年6月6日
    0103
  • 超好用的UnixLinux 命令技巧 大神为你详细解读

    1、删除一个大文件 我在生产服务器上有一个很大的200GB的日志文件需要删除。我的rm和ls命令已经崩溃,我担心这是由于巨大的磁盘IO造成的,要删除这个大文件,输入: > /…

    Linux 2023年6月14日
    0106
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球