欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Kotlin结合Rxjava+Retrofit实现极简网络请求的方法

程序员文章站 2024-01-20 19:37:52
前言 因为最近正在写的项目集成了两个网络请求框架(volley and retrofit)对比之下也是选择了retrofit。既然选择那自然要让自己以后开发更加省力(就是...

前言

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

Kotlin结合Rxjava+Retrofit实现极简网络请求的方法

kotlin镇楼

rxjava

rxjava学习是一个曲折漫长的过程,但一旦掌握,妙用无穷。

通过这里了解更多:

retrofit

retrofit与okhttp共同出自于square公司,retrofit就是对okhttp做了一层封装。把网络请求都交给给了okhttp,我们只需要通过简单的配置就能使用retrofit来进行网络请求了,其主要作者是android大神jakewharton。

导包:

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'//retrofit2所需要的包
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'//converterfactory的gson依赖包
compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'//converterfactory的string依赖包

*这里需要值得注意的是:导入的retrofit2包的版本必须要一致,否则就会报错。

通过这里了解更多:

正文

导包

首先需要导入相关的包,包括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:端口/后台项目名/,需要以/结尾。而后的addconverterfactory和addcalladapterfactory是我们刚刚导入的包,用于添加gson和rxjava支持,其中如果解析的时候有要求时间格式,可自定义一个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") }){
 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,不实现也可以
 })

总结

以上就是这篇文章的全部内容了,这里的一些实现方式不止用在这里,这篇文章也只是当做一个抛砖引玉,其中可能也有很多操作不到位,讲的不到位的,希望喷的小声点,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。