Android中使用Kotlin协程(Coroutines)和Retrofit进行网络请求(三)之异常处理与封装

本文介绍了如何在Android中使用Kotlin协程和Retrofit进行网络请求时处理异常和封装。通过枚举类定义异常类型,创建网络请求类并利用LiveData确保UI安全。在Repository和ViewModel中进行数据处理,简化UI类代码,确保在生命周期内安全执行网络操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 写在前面
    前面文章介绍了一些kotlin协程和retorfit结合进行网络请求的基础,但是如果在前面的demo执行的过程中,我们断开手机网络,会发生什么?没错,APP会因为IO异常而崩溃!为什么呢,这是因为retrofit在执行excute()方法时会throws IOException,而enqueue()方法则不会,因为它会把IOException处理放在callback的onFailure方法里.所以如果我们需要使用excute()方法就需要手动处理异常.

  • 异常的分类
    当一个网络请求得到的结果并非是你的期望值,我们就可以看作是请求异常,那么请求异常有哪些原因呢,我把请求异常分为三类:
    第一类,网络问题,可能是设备网络未连接,连接信号弱,网络拥堵,等等原因,这就是IOException;
    第二类,连接服务器问题,我们都知道正常的网络访问结果返回的code是200,如果返回502,404等,那就是服务器,可能是请求地址有问题可能是请求方式有问题或者服务器原因,这种在retrofit中也有表达;
    第三类,返回值异常,就是服务器能正常返回给你数据,但是数据不是你想要的,这就是逻辑问题,可能你的参数不对,可能后端处理不对,也可能根据你的请求本身逻辑就应该显示这种异常.这种需要根据你项目具体的接口文档进行决定,需要自行对结果进行判断
    好,类型定了,那就先用代码表现出来,先写一个枚举类

    enum class ErrorType {
         
         
        NETWORK_ERROR,//网络出错
        SERVICE_ERROR,//服务器访问异常
        RESPONSE_ERROR//请求返回值异常
    }
    

    再来一个错误类用于封装错误信息

     /**
     * 网络请求出错的响应
     */
    data class ErrorResponse(
        val errorType:ErrorType,//错误类型
        val errorTag:String,//错误tag,用于区别哪个请求出错
        val errorCode: String?,//错误代码
        val message: String?//错误信息
    )
    
  • 创建ApiSerevice
    retrofit需要创建一个接口类,不过我们在kotlin中可以对这个类直接进行初始化,上一篇文章中已经演示了如何通过伴生对象直接获取retrofit单例实例(实际上接口没办法做到真正的单例,因为无法私有构造函数)这次我们通过invoke()函数的方式来实例化retrofit,至于单例,实际项目中可以通过依赖注入框架来实现,话不多说先上代码

    interface ApiService {
         
         
    
        @POST("versionupdate/getCurrentAppVersion")
        fun getCurrentAppVersion(@Query("json") json:String) :Call<UpdateResult>
    
        @POST("userinfo/signin")
        fun userLogin(@Query("json") json:String):Call<LoginResult>
    
        companion object {
         
         
    		//operator 是构造函数操作符, operator fun invoke()相当于是实现java的构造函数
            operator fun invoke(): ApiService {
         
         
                //自定义一个拦截器,打印请求地址和请求结果
                val paramInterceptor = Interceptor{
         
          chain ->
                    val url = chain.request().url().url().toString()
    
                    LogUtil.d("发送请求:${URLDecoder.decode(url,"utf-8")}")
                    val response = chain.proceed(chain.request())
                    //注意这里不能直接使用response.body.string(),否则流会关闭,会报异常
                    val responseBody = response.peekBody(1024*1024)
                    LogUtil.d("请求结果:${
           
           responseBody.string()}")
                    return@Interceptor response
                }
    
                val okHttpClient = OkHttpClient.Builder()
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值