美文网首页
kotlin扩展封装Rxjava及配合Retrofit使用

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

作者: 如沙雨下 | 来源:发表于2019-01-02 21:57 被阅读23次

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

    1. 接口格式

    正常情况接口返回格式:

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

    异常情况返回格式:

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

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

    open class BaseResult<T> {
        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<BaseResult<LoginBean>>
    

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

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

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

    重点来了

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

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

    class RxStreamHelper {
        fun <T> io_Main(): ObservableTransformer<BaseResult<T>, 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 <T> Observable<BaseResult<T>>.dispatchDefault(): Observable<T> =
        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 <T : Any> Observable<T>.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使用

          本文链接:https://www.haomeiwen.com/subject/ktptrqtx.html