kotlin扩展封装Rxjava及配合Retrofit使用

最近开始用kotlin写新项目,由于后台接口调用业务成功和失败时返回的数据格式不一致,需要修改原来的网络请求封装,写个博客分享下一些kotlin扩展封装的小技巧

1. 接口格式

正常情况接口返回格式:

{
    "data": {
       ...
    },
    "success":true
 }

异常情况返回格式:

 {
    "errorCode":"1002",
    "errorMsg":"账户不存在",
    "success":false
}

为了统一2种数据格式,封装一个BaseResult:

open class BaseResult {
    val errorCode: String = ""
    val errorMsg: String = ""
    val success: Boolean = false
    var data: T? = null
}

每次如果调用成功则只需要data对象,如失败需要toast弹errorMsg或针对errorCode处理相应逻辑

2. 扩展封装

@POST("fshows.market.api.user.login")
fun login(@Body request: LoginRequest): Observable>

通常在使用Rxjava+retrofit时每个接口都需要写2句重复的切换线程的方法,如果是用java语言开发我们一般可以通过compose操作符把这2句方法封装成一个函数,而在使用kotlin时由于有扩展函数这种方便的语法糖,比java简洁很多:

fun  Observable.dispatchDefault(): Observable =
    this.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())

只需一句.dispatchDefault()就完了,是不是很简单?

重点来了

回到上边的需求,那么怎么用kotlin处理接口成功和失败2中不同的数据格式呢?

如过不使用kotlin扩展的话需要用到ObservableTransformer

class RxStreamHelper {
    fun  io_Main(): ObservableTransformer, T> {
        return ObservableTransformer { upstream ->
            upstream.subscribeOn(Schedulers.io())
                //解析data层,剔除 code /msg
                .flatMap { tBaseModel ->
                    if (tBaseModel.success) {
                        Observable.just(tBaseModel.data!!)
                    } else Observable.error(ApiException(tBaseModel.errorCode.toInt(), tBaseModel.errorMsg))
                }
                .observeOn(AndroidSchedulers.mainThread())
        }
    }
}

而如果用扩展来写的话

fun  Observable>.dispatchDefault(): Observable =
    this.subscribeOn(Schedulers.io())
            //解析data层,剔除 code /msg
            .flatMap { tBaseModel ->
                if (tBaseModel.success) {
                    Observable.just(tBaseModel.data!!)
                } else Observable.error(ApiException(tBaseModel.errorCode.toInt(), tBaseModel.errorMsg))
            }
            .observeOn(AndroidSchedulers.mainThread())

看了上边的代码吧,其实非常简单哈,用flatMap操作符解析data层的同时就完成了接口成功失败的判断

来看下api的调用代码:

ApiService.login(LoginRequest("username", MD5Utils.getStringMD5("pwd")))
        .dispatchDefault()
        .subscribeBy(
                onNext = {
                    startActivity(Intent(this@LoginActivity, MainActivity::class.java))
                }
        )

非常简洁清爽有木有,上边的subscribeByrxkotlin库里的扩展函数,为了实现接口返回失败时弹toast我又写了个自己的扩展:

private val onNextStub: (Any) -> Unit = {}
//重写rxkotlin,全局toast异常
private val onErrorStub: (Throwable) -> Unit = { Toast.makeText(App.getContext(), it.message, Toast.LENGTH_SHORT).show() }
private val onCompleteStub: () -> Unit = {}

/**
 * Overloaded subscribe function that allows passing named parameters
 */
fun  Observable.subscribeNext(
        onError: (Throwable) -> Unit = onErrorStub,
        onComplete: () -> Unit = onCompleteStub,
        onNext: (T) -> Unit = onNextStub
): Disposable = subscribe(onNext, onError, onComplete)

把上边的subscribeBy换成自己写的扩展subscribeNext就ok了

结语

kotlin的扩展封装的简单应用,感谢阅读,抛砖引玉,欢迎各位交流kotlin的开发技巧

你可能感兴趣的:(kotlin扩展封装Rxjava及配合Retrofit使用)