继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

用Kotlin的方式来处理网络异常

fengzhizi715
关注TA
已关注
手记 72
粉丝 1.7万
获赞 594
一. 前言

之前的文章 RxJava处理业务异常的几种方式 曾经介绍过 Retrofit 的异常可以有多种处理方式。

其中,可以使用 RxJava 的错误处理操作符,它们是专门用来处理异常的。

随便例举两个操作符:

onErrorReturn 操作符,表示当发生错误的时候,发射一个默认值然后结束数据流。所以 Subscriber 看不到异常信息,看到的是正常的数据流结束状态。

onErrorResumeNext 操作符,表示当错误发生的时候,使用另外一个数据流继续发射数据。在返回的被观察者中是看不到错误信息的。

二. 使用 Kotlin 的特性

这次我结合 Kotlin 扩展函数的特性来尝试处理异常。

网络请求返回的 Response 大多是采用如下这种形式:

{
   "code":0,
   "message":"success",
   "data":{
       ...
    }
}

对于客户端开发而言,我们会封装一个基类的HttpResponse。

data class HttpResponse<T>(
        var code: Int = -1, //0: 成功 1: xxx错误或过期 2: 业务逻辑错误 500:系统内部错误 998表示Token无效
        var message: String? = null,
        var data: T? = null
) : UnProguard {
    val isOkStatus: Boolean
        get() = code == 0
}

其中,UnProguard是一个空的接口,主要是方便 App 在混淆的时候保留部分类。

interface UnProguard : Serializable

通常情况下,我们会在 Observer 的 onError 中按照如下的方式处理异常:

        viewModel.getHelps(this)
                .subscribe({
                    if (it.isOkStatus) {
                        multi_status_view.showContent()
                        adapter.addData(it.data?.list)
                    } else {
                        multi_status_view.showError()
                    }
                }, { multi_status_view.showError() })

如果我们利用 RxJava 的错误处理操作符,可以编写如下的扩展函数:

import com.safframework.utils.RetryWithDelay
import io.reactivex.Maybe

/**
 *
 * @FileName:
 *          cn.magicwindow.core.ext.`Maybe+Extension`.kt
 * @author: Tony Shen
 * @date: 2018-07-19 17:31
 * @version V1.0 <描述当前版本功能>
 */

/**
 * 尝试重试
 * 默认有3次重试机会,每次的延迟时间是1000ms
 */
fun <T> Maybe<T>.retryWithDelayMillis(maxRetries: Int=3, retryDelayMillis: Int=1000): Maybe<T> =
        this.retryWhen(RetryWithDelay(maxRetries,retryDelayMillis))

/**
 * 遇到错误时,能够提前捕获异常,并发射一个默认的值。
 * 后面无须再做异常处理
 */
fun <T> Maybe<T>.errorReturn(defValue:T): Maybe<T> = this.onErrorReturn {

    it -> it.printStackTrace()
    return@onErrorReturn defValue
}

fun <T> Maybe<T>.errorReturn(defValue:T,action: (Throwable) -> Unit): Maybe<T> = this.onErrorReturn {

    action.invoke(it)

    return@onErrorReturn defValue
}

/**
 * 遇到错误时,能够提前捕获异常,并返回一个新的Maybe
 * 后面无须再做异常处理
 */
fun <T> Maybe<T>.errorResumeNext(defValue:T):Maybe<T> = this.onErrorResumeNext(Maybe.just(defValue))

fun <T> Maybe<T>.errorResumeNext():Maybe<T> = this.onErrorResumeNext(Maybe.empty())

扩展函数 errorReturn 的使用:

        viewModel.getHelps(this)
                .errorReturn(HttpResponse()) {
                    multi_status_view.showError()
                }
                .subscribe{
                    if (it.isOkStatus) {
                        multi_status_view.showContent()
                        adapter.addData(it.data?.list)
                    } else {
                        multi_status_view.showError()
                    }
                }

这样无须在 onError 中处理异常,而且 errorReturn 还是一个高阶函数。它的 action 参数传递的是一个函数,专门用于处理异常。每一个网络请求的异常处理并不会都一样,可以用该函数来传递不同的异常处理。

总结

合理利用 Kotlin 的扩展函数,可以编写优雅的代码。而使用高阶函数,则可以达到的进一步的抽象。

打开App,阅读手记
5人推荐
发表评论
随时随地看视频慕课网APP