Kotlin基于RxJava的扩展方法(超级好用)

Kotlin扩展方法

Kotlin的好处有很多,其中有一个超级好用的就是扩展方法。

目前来讲,大多数的项目架构都是采用MVP+Rxjava+Dagger2+Retrofit2+AutoDispose+ARouter等等来进行封装的。
今天我们主要来看看对于RxJava的扩展方法,超级好用。

一个是统一的数据解析处理,另一个是统一的线程切换和自动解绑

关于MVP架构的可以看 MVC到MVP的过渡

统一的线程切换和自动解绑的扩展方法

之前我写过一篇博客,主要是介绍 AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题

还写了 Rxjava2线程调度及Observer的封装 这篇文章,感兴趣的可以先了解一下。

之前的办法我们并没有进行一个统一的封装,导致我们每次在使用IRxJava的时候都要分别调用一下,类似这样

 Observable.just("1")
            .compose(RxSchedulers.io2main())//切换线程
            .autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_DESTROY))//OnDestory时自动解绑
            .subscribe {
            }

下面,我们来写一个扩展方法,同时实现线程调度和自动解绑

首先新建一个kotlin文件(注意,后缀名是.kt)
例如RxExtend.kt ,否则可能出现找不到扩展方法的情况,直接写扩展方法即可,不用写在class里面,否则也会找不到

在这里插入图片描述
因为线程切换和自动解绑都是针对于Observable的,我们先来看一下Observable的源码

Kotlin基于RxJava的扩展方法(超级好用)_第1张图片
Observable是一个抽象类,我们在该类的基础上进行扩展即可,代码如下

名字可以自己随便起,我这里就用transform(转换)表示了

/*
* 对Observable进行线程调度和生命周期绑定
*
* */
fun  Observable.transform(owner: LifecycleOwner): ObservableSubscribeProxy {
    return this.compose(RxSchedulers.io2main()).autoDisposable(AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY))
}


扩展方法这样就写好了,其实就是把线程切换和自动解绑封装了下,不过使用扩展方法不会打乱原有的链式结构,Java的话就做不到了。

下面我们来用一用:

  Observable.just("1")
            .transform(this)
            .subscribe {
                
            }

这样一来,我们直接通过调用.transform(this)即可实现线程切换和自动解绑了,是不是更加方便了呢.

统一对接口返回的数据进行处理

正常来讲,我们在开发之前要跟后台定好一个协议,规范返回的数据,

例如:(这里我只是举个例子,实际返回的字段是你跟后台你们自己商量):
我们约定,返回的数据字段只有3个,分别是result,reason,error_code

1. error_code用来确定返回的数据是否正确,0代表成功 -1表示失败
2. reason 表示返回数据时的描述
3. result 返回的具体数据,可能是个json对象,也可能是个json’数组

返回的json结构如下:

{"reason":"成功的返回","result":{},"error_code":0}
或
{"reason":"成功的返回","result":[{},{}],"error_code":0}

对接口返回的数据进行处理是我们经常要做的,比较麻烦的做法就是对每个接口返回的数据生成一个实体类,然后在onNext中进行判断处理。

但是这样一来接口比较多的话就很不好维护了,那我们能不能扩展一个方法,统一对数据进行判断,如果返回正确的话,就把数据传到onNex里,不正确的话就把错误信息传到onError里。

这就好办了,下面我们来声明一个实体类,如下
数据解析我使用的是Gson
其中
result是个泛型类型的,因为我们不知道具体返回的数据到底是什么

/**
 * @Description: 服务端返回数据基类
 * @author : yzq
 * @date   : 2018/7/2
 * @time   : 14:11
 *
 */
data class BaseResp(
        var reason: String = "", // 成功的返回
        var result: T,
        @SerializedName("error_code")
        var errorCode: Int = 0 // 0
) 

RxJava一般都和Retrofit进行配合使用,举个例子,我们要获取新闻列表。

这里我用的是聚合的一个接口,他返回的数据是这样:

{
	"reason": "成功的返回",
	"result": {
		"stat": "1",
		"data": [{
			"uniquekey": "0bb54602fcc15111afca8452cc127d57",
			"title": "口香糖销量下降30%,你一定猜不到原因",
			"date": "2019-03-06 12:55",
			"category": "头条",
			"author_name": "解放网",
			"url": "http:\/\/mini.eastday.com\/mobile\/190306125558115.html",
			"thumbnail_pic_s": "http:\/\/01imgmini.eastday.com\/mobile\/20190306\/20190306125558_d2b6545a4b6273201218c32c6ffe436a_1_mwpm_03200403.jpg"
		}, {
			"uniquekey": "c92887585d01563c077c7be7f23dca87",
			"title": "《还珠格格》中的演员都老了,网友:五阿哥还是很帅",
			"date": "2019-03-06 12:44",
			"category": "头条",
			"author_name": "北青网",
			"url": "http:\/\/mini.eastday.com\/mobile\/190306124440102.html",
			"thumbnail_pic_s": "http:\/\/04imgmini.eastday.com\/mobile\/20190306\/20190306124440_bfad5f823d7fcad5e044754e095278ef_1_mwpm_03200403.jpg",
			"thumbnail_pic_s02": "http:\/\/04imgmini.eastday.com\/mobile\/20190306\/20190306124440_bfad5f823d7fcad5e044754e095278ef_4_mwpm_03200403.jpg",
			"thumbnail_pic_s03": "http:\/\/04imgmini.eastday.com\/mobile\/20190306\/20190306124440_bfad5f823d7fcad5e044754e095278ef_2_mwpm_03200403.jpg"
		}]
	},
	"error_code": 0
}

首先我们要对result返回的数据生成一个实体类(NewBean),如下


data class NewsBean(var stat: String = "", // 1
                    var data: List = listOf()) {
    data class Data(

            @Expose
            var uniquekey: String = "", // fe1989479c791a1898852edf3b7ed001
            @Expose
            var title: String = "", // 古装美人饮酒,赵丽颖俏皮,李沁优雅,杨幂豪爽,而她秒杀众人
            @Expose
            var date: String = "", // 2018-07-13 14:17
            @Expose
            var category: String = "", // 头条
            @Expose
            @SerializedName("author_name")
            var authorName: String = "", // 北青网
            @Expose
            var url: String = "", // http://mini.eastday.com/mobile/180713141718664.html
            @Expose
            @SerializedName("thumbnail_pic_s")
            var thumbnailPicS: String = "", // http://05.imgmini.eastday.com/mobile/20180713/20180713141718_bebdf00d5070a17241f48e305bc76f75_3_mwpm_03200403.jpg
            @SerializedName("thumbnail_pic_s02")
            @Expose
            var thumbnailPicS02: String = "", // http://05.imgmini.eastday.com/mobile/20180713/20180713141718_bebdf00d5070a17241f48e305bc76f75_4_mwpm_03200403.jpg
            @SerializedName("thumbnail_pic_s03")
            @Expose
            var thumbnailPicS03: String = "" // http://05.imgmini.eastday.com/mobile/20180713/20180713141718_bebdf00d5070a17241f48e305bc76f75_5_mwpm_03200403.jpg


    )
}

请求接口如下,返回一个Observable>


interface ApiService {

    @POST(ServerContants.Url.index)
    @FormUrlEncoded
    fun getIndex(@Field(ServerContants.parameter.type) type: String, @Field(ServerContants.parameter.key) key: String): Observable>

}

下面我们来针对这种格式的数据进行统一的解析处理:
这里要注意,是Observable>进行扩展的,还是那句话,你想对谁做处理,就扩展谁

/*
* 数据转换
*
* */
fun  Observable>.dataConvert(): Observable {
    return flatMap {
        if (it.errorCode == 0) Observable.just(it.result) else Observable.error(Throwable(message = it.reason))
    }

下面我们来配合上面的扩展来一起使用

        RetrofitFactory.instance.getService(ApiService::class.java)
                .getIndex(type, key)
                .dataConvert()
                .transform(this)
                .subscribe {
                    it.data
                }
   

这样用起来是不是代码很简洁

然后你再结合你自己的项目结构,跟Observer进行一下整合,是非常好用的,并且很好维护的。

下面给出所有代码:


/**
 * @description: 线程调度封装
 * @author : yzq
 * @date   : 2018/7/9
 * @time   : 15:19
 *
 */

class RxSchedulers {

    companion object {

        fun  io2main(): ObservableTransformer {

            return ObservableTransformer { upstream ->
                upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())

            }

        }

    }

}

扩展文件:


/**
 * @description: 对RxKotlin的扩展
 * @author : yzq
 * @date   : 2018/7/9
 * @time   : 15:36
 *
 */

/*
* 对Observable进行线程调度和生命周期绑定
*
* */
fun  Observable.transform(owner: LifecycleOwner): ObservableSubscribeProxy {
    return this.compose(RxSchedulers.io2main()).autoDisposable(AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY))
}


/*
* 数据转换
*
* */
fun  Observable>.dataConvert(): Observable {
    return flatMap {
        if (it.errorCode == ResponseCode.SUCCESS) Observable.just(it.result) else Observable.error(Throwable(message = it.reason))
    }



}

同样的,我们还可以对其他类进行扩展,只要是你有需求,感觉代码不简洁的,都可以用扩展来实现。

如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

你可能感兴趣的:(Android,kotlin)