Kotlin结合Rxjava和Retrofit做到极简网络请求

前言

由于当前正在写的项目集成了两个网络请求框架(Volley and Retrofit)对比之下也是选择了Retrofit。既然选择那自然要让自己以后开发更加省力(就是懒)。于是我在Retrofit中加入了Rxjava,这也是当下蛮流行的一个请求框架。然后又利用了Kotlin的一些新特性,使网络请求变得特别简单,代码量特别少。


Kotlin镇楼

正文

导包

首先需要导入相关的包,包括Rxjava(我这里使用的是1.x的版本,如果你使用的是2.x的版本影响不大)、Retrofit。

    //Rxjava
    compile 'io.reactivex:rxandroid:1.2.0'
    compile 'io.reactivex:rxjava:1.2.0'
    //Retrofit
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

初始化Retrofit

      retrofit = Retrofit.Builder()
                .client(build.build())
                .baseUrl("你的url")
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build().create(RetrofitUrl::class.java)

client传入的是一个OkhttpClient,这里我们需要创建一个OkhttpClient对象,这个可以用来加入一些拦截器、连接等待时间等,以下是我的client

        val build = OkHttpClient.Builder().connectTimeout(15,TimeUnit.SECONDS)
                .writeTimeout(15,TimeUnit.SECONDS)
                .readTimeout(15,TimeUnit.SECONDS)
        val logging = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
            Log.e("retrofit url",it)
        })
        logging.level = HttpLoggingInterceptor.Level.BODY

我这里只设置了连接、读、写超时时间和一个拦截器,用于在用Retrofit请求网络的时候可以获取到请求的信息。然后是baseUrl这里是设置网络请求的通用的地址,格式类似于http://ip:端口/后台项目名/,需要以/结尾。而后的addConverterFactoryaddCallAdapterFactory是我们刚刚导入的包,用于添加gsonRxJava支持,其中如果解析的时候有要求时间格式,可自定义一个gson传入:

val gson = GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create()

如果不要求时间格式,GsonConverterFactory.create(此处可以不传参数)。然后就是RetrofitUrl,这是一个接口,名字可以根据个人喜好进行定义,其内放置请求的接口:

interface RetrofitUrl {
    //方法名自定义
    @GET("接口地址")
    fun load():Observable<对应实体类>

    @FormUrlEncoded
    @Post("接口地址")
    fun load():Observable<对应实体类>

    //需要传递参数,多个参数逗号隔开
    @GET("接口地址")
    fun load(@Query("参数名字") 参数名字(可自定义):参数类型):Observable<对应实体类>

    @FormUrlEncoded
    @Post("接口地址")
    fun load(@Field("参数名字") 参数名字(可自定义):参数类型):Observable<对应实体类>

    //示例
    @GET("load")
    fun load():Observable<NetOuter<Orgs>>

    @GET("load")
    fun load(@Query("id") id:Int):Observable<NetOuter<Orgs>>
}

以上就是初始化大概过程,初始化我是放在了自定义的Application中完成,使用时通过Application获取到Retrofit

请求网络

以上都做完了就可以开始请求网络了。
通过Application获取到Retrofit后,我们就可以通过它去调用我们刚刚在接口中定义的方法,因为配置了RxJava,所以调用方法后会返回一个Observable,这也是我们在接口中定义的返回类型,如果没有添加RxJava,返回类型为Call。这样子我们就可以按照RxJava的习惯去写了:

  retrofit().load()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object :Subscriber<NetOuter<Orgs>>(){
                override fun onCompleted() {
                               
                }
                override fun onNext(t: NetOuter<Orgs>?) { 
                      //可以在这里对获取到的数据进行处理
                }
                override fun onError(e: Throwable?) { 
                     //请求失败
                }
             )

这样子我们就完成了一个网络请求,这里就进行了线程调度的操作,具体看操作者的需求,也可以加入以下RxJava的操作符。
虽然这样子可以进行网络请求,可如果每次请求都要去写线程调度又觉得太麻烦了,都是一样的代码。这时候我们就用到了Kotlin的一个特性,扩展函数。我们新建一个Kotlin File文件,在其中写入我们修改了的代码:

fun <T> runRx(observable: Observable<T>, subscriber: Subscriber<T>): Subscription = 
    observable.subscribeOn(Schedulers.io())
              .observeOn(AndroidSchedulers.mainThread())
              .subscribe(subscriber)

让我们调调这个方法看看效果:

runRx(retrofit().load(),object : Subscriber<NetOuter<Orgs>>() {
        override fun onCompleted() {}

        override fun onNext(t: NetOuter<Orgs>?) { 
            //可以在这里对获取到的数据进行处理
        }

        override fun onError(e: Throwable?) { 
            //请求失败
       }
)

通过这一层的封装,省去了线程调度的代码,在大量请求的时候,可以省去不少代码。但是,就这个程度,还是觉得要一直写object : Subscriber...,这个也不想写,懒嘛。怎么办?只能继续封装,这时候就想到了Kotlin的另一个特性,高阶函数。Kotlin允许把一个方法当做一个参数进行使用,使用时通过Lambda的方式展示,一样在我们刚刚写runRx那个文件:

fun <T> runRxLambda(observable: Observable<T>,next:(T)->Unit,error:(e: Throwable?)->Unit,completed:() -> Unit = { Log.e("completed","completed") }): Subscription{
    runRx(observable, object : Subscriber<T>() {
        override fun onCompleted() { completed }
        override fun onNext(t: T) { next(t) }
        override fun onError(e: Throwable?) { error(e) }
    })
}

这里通过next:(T)->Unit将方法当做一个参数,其中next为这个参数的参数名字,冒号后面的括号里面为这个方法需要的参数,多个参数逗号隔开,Unit是返回类型,Unit相当于Java中的void。其中还看到了completed:() -> Unit = { Log.e("completed","completed") }这里用到了Kotlin的参数默认值,通过=号将右边当做左边方法的默认实现,如果操作者没有实现这个方法,就用这个默认操作。runRxLambda的方法内也就是调用了我们刚刚写的runRx方法,然后将对应的方法传入就可以了。接下来看看效果:

runRxLambda(retrofit().load(),{
        //我们在这里的操作就相当于在onNext中的操作,参数可以通过it获取
    },{
        //这里就是onError的实现,参数也可以通过it获取
    })

runRxLambda(retrofit().load(),{
        //我们在这里的操作就相当于在onNext中的操作,参数可以通过it获取
    },{
        //这里就是onError的实现,参数也可以通过it获取
    },{
       //这里是onCompleted,不实现也可以
    })

结尾

以上就是所有的内容了,这里的一些实现方式不止用在这里,这篇文章也只是当做一个抛砖引玉,其中可能也有很多操作不到位,讲的不到位的,希望喷的小声点。有什么更好的想法也希望可以私信留言。

源码 ======> Github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容