Kotlin封装RxJava与Retrofit

小说:微信如何升级零钱通作者:帝华更新时间:2019-01-24字数:58621

“水遁·海之愤怒。“白虎站起身来,一对前爪用力在海上狠狠一拍,脚下的大海以更加剧烈的频率翻滚起来,宛如大海真的愤怒了,要毁灭海上的一切似的,一道道高十几米宽三米,密度极大的超高压海浪一波接一波的挡在了白虎的面前在千钧一发之际挡住了天照之火。

挂机联盟软件下载

钱诺连忙祭起了他化自在天魔幡,他化自在天魔幡之上放出了一圈圈的琉璃色光华,护在自己的头上,铁尺之上放出的光气打在琉璃色光华之上,直接将这琉璃色光华给打碎。
果然,明珠呆了一下,她的脸蓦地羞得通红,丢下李庆安的手,便向内宅跑去。

“第二也是和第一有关系,两个原因加起来才会促使我这么做,如果没有第二个原因的话,那么就算要和你再赌一次我也不会做出这样的事情。”

代码地址:https://github.com/DarkPointK/RxTrofit.git
前言

       Retrofit是Square公司开发的一个类型安全的Java和Android 的REST客户端库。来自官网的介绍:

A type-safe HTTP client for Android and Java

Rest API是一种软件设计风格,服务器作为资源存放地。客户端去请求GET,PUT, POST,DELETE资源。并且是无状态的,没有session的参与。

  • retrofit模型如下:
  1. POJO或模型实体类 : 从服务器获取的JSON数据将被填充到这种类的实例中。
  2. 接口 : 我们需要创建一个接口来管理像GET,POST...等请求的URL,这是一个服务类。
  3. RestAdapter类 : 这是一个REST客户端(Rest Client)类,retrofit中默认用的是Gson来解析JSON数据,你也可以设置自己的JSON解析器。

Retrofit是基于OkHttp的网络接口的封装,之所以被中小型项目所推行使用,还是得力于它的相对规范化、安全性、可操作性

 

RxJava 在 GitHub 主页上的用这样一句话形容自己是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准,但这句话更像是对RxJava的一个总结。其实, 简单来说RxJava 的本质可以压缩为异步这一个词。说到根上,它就是一个实现异步操作的库,而别的定语都是基于这之上的。用我个人的话来说,RxJava既是AsyncTask 的终极形态。

准备工作

       前面,我们简单的了解了一下Retrofit与RxJava,本文的着重点在大家已经会用的前提下,还是要和大家探讨如何去应用以及封装他们。想要在项目中使用他们,第一步便是在Gradle中添加相应的Dependencies:

    compile "com.squareup.retrofit2:retrofit:2.3.0"

    compile "com.squareup.retrofit2:converter-gson:2.3.0"//retrofit2的Json转换器(默认用Gson)

    compile "com.squareup.okhttp3:okhttp:3.9.0"

    compile "com.squareup.okhttp3:logging-interceptor:3.9.0"//okhttp提供的请求日志拦截器

    compile "io.reactivex:rxjava:1.3.0"

    compile "io.reactivex:rxandroid:1.2.1"

compile "com.squareup.retrofit2:adapter-rxjava:2.3.0"

简单封装

接下来,创建必要的类与接口,当然,别忘了manifests中添加权限:

<uses-permission android:name="android.permission.INTERNET"/>

新建一个提供给Retrofit初始化,用于描述服务端接口的Interface,我在这里调用的是豆瓣的一个公开接口:

1 interface HttpInterface {
2 
3     @GET("top250")
4 
5     fun getTopMovie(@Query("start") start: Int, @Query("count") count: Int): Observable<GetMovie>
6 
7 }

这里定义了一个GET目录top250,参数为start,count,返回值则是一个Observable绑定了一个接口返回数据的实体类

 

接着新建一个用于初始化Retrofit封装请求的方法类:

 1 class HttpMethod {
 2 
 3     companion object {
 4 
 5         val httpMethod: HttpMethod = Holder.INSTANCE
 6 
 7     }
 8 
 9     private object Holder {
10 
11         val INSTANCE = HttpMethod()
12 
13     }
14 
15 }
16 
17  

由于网络请求在业务逻辑中将频繁的被调用,所以需要我们在这里创建一个当前类的单例,以避免被多次实例化。

 

       当我们创建好单例后,便可以放心的来初始化我们即将需要用到的3个关键的成员变量了,retrofit的回调适配器我们在这选用RxJavaCallAdapterFactory:

 1 private var okclient = OkHttpClient.Builder()
 2 
 3      .addInterceptor(HttpLoggingInterceptor().
 4 
 5 setLevel(HttpLoggingInterceptor.Level.BODY))
 6 
 7    .addNetworkInterceptor(OAuthIntercepter())
 8 
 9      connectTimeout(8, TimeUnit.SECONDS)
10 
11      readTimeout(15, TimeUnit.SECONDS)
12 
13      writeTimeout(15, TimeUnit.SECONDS)
14 
15      build()
16 
17  
18 
19 private var retrofit: Retrofit = Retrofit.Builder()
20 
21      .client(okclient)
22 
23      .baseUrl("https://api.douban.com/v2/movie/")
24 
25      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
26 
27      .addConverterFactory(GsonConverterFactory
28 
29 .create(GsonBuilder().serializeNulls().setLenient().create())
30 
31 )
32 
33      .build()
34 
35  
36 
37 private var httpInterface = retrofit.create(HttpInterface::class.java)
38 
39  

 

我们首先Builder了一个OkhttpClient对象,并为其添加了一个请求日志的拦截器,紧接着初始化了Retrofit为其添加RxJavaCallAdapter,最后以HttpInterface为参数将retrofit创建为HttpInterface,这样我们就可以用httpInterface封装一个调用之前所描述的getTopMovie接口方法,在这个方法中我们会将Retrofit完成请求返回的被观察者订阅起来,在这个过程中我们可以对返回的数据流通过RxJava丰富的操作符进行自由的处理。

 

       定义一个getTopMovie方法用于在业务逻辑中调用retrofit接口,这里我们需要三个参数,其中前两个为GET请求所需要的参数,而subscriber用来订阅retrofit接口返回的Observable:

1 fun getTopMovie(start: Int, count: Int, subscriber: Subscriber<GetMovie>) {}

这样我们便可以在客户端的业务逻辑中通过调用HttpMethod. INSTANCE .getTopMovie(…)来请求接口,但是此时我们还没有将Observable订阅上,所以现在我们需要完善下这个方法:

1 fun getTopMovie(start: Int, count: Int, subscriber: Subscriber<GetMovie>) {
2 
3         toSubscriber(httpInterface.getTopMovie(start,count),subscriber)
4 
5     }

可以看到我们在方法体中添加了一句toSubscriber(…),至此我们便将subscriber订阅上httpInterface.getTopMovie(…)返回的Observable了,至于这个subscriber参数具体如何实现,在下一节将会介绍,我们先来了解下这个toSubscriber的工作是如何实现的:

 1 private fun toSubscriber (observable: Observable<T>, subscriber: Subscriber<T>) {
 2 
 3         observable.subscribeOn(Schedulers.io())
 4 
 5                 .unsubscribeOn(Schedulers.io())
 6 
 7                 .observeOn(AndroidSchedulers.mainThread())
 8 
 9                 .doOnError {}
10 
11                 .subscribe(subscriber)
12 
13     }

熟悉RxJava的码友应该一眼变冷看出这是一段典型的订阅流程,是的,这是通过RxJava流式编程实现最简单的订阅事件。

至此,我们便已经可以再业务逻辑中正常使用getTopMovie(…)了:

 1 HttpMethod.httpMethod.getTopMovie(1,1,object :Subscriber<GetMovie>(){
 2 
 3             override fun onNext(t: GetMovie?) {
 4 
 5             }
 6 
 7  
 8 
 9             override fun onCompleted() {
10 
11             }
12 
13  
14 
15             override fun onError(e: Throwable?) {
16 
17             }
18 
19  
20 
21         })
进阶用法

       我们已经知道如何简单的方式通过RxJava调用Retrofit接口,但这往往不能的满足我们的追求。

在项目中,往往我们会定义这样的返回体结构:

{

    "code": 1,

    "data": [ ],

    "msg": "success"

}

 

我们会在所有接口得到3个全局相应参数,其中code代表结果码,msg代表附加信息,而data则是对应的响应数据会因接口而异,我们往往需要每个接口根据code去判断接下来的操作,那么我们应该怎样封装才能让每个统一进行处理呢,接下来我们改一改前面的订阅流程:

data class GetMovie<T>(

              @SerializedName("count") var count: Int?, //20

              @SerializedName("start") var start: Int?, //0

              @SerializedName("total") var total: Int?, //250

              @SerializedName("subjects") var subjects: T?,

              @SerializedName("title") var title: String? //豆瓣电影Top250

)

 

这里我们切当subjects以外的参数为固有的全局响应参数,而subjects的List元素类型则不定,我们需要显示的绑定GetMovie以在订阅时可以取得全局响应参数而不用关心subjects的类型,改动的包括接口定义在内用到实体类泛型的地方:

interface HttpInterface {

    @GET("top250")

    fun getTopMovie(@Query("start") start: Int, @Query("count") count: Int): Observable<GetMovie<List<Subject>>>

}

 

接口表示我们获取到的返回数据将会是GetMovie类的结构,并且泛型指出subjects的类型是个Subject的List,接下来在将HttpMethod中封装请求的方法也修改下:

fun getTopMovie(start: Int, count: Int, subscriber: Subscriber<List<Subject>>) {

        toSubscriber(httpInterface.getTopMovie(start, count), subscriber)

    }

由于我们需要在RxJava处理数据的流程中,统一对全局响应参数进行判断,所以订阅的流程便成为了我们工作主要进行的场所:

 1 private fun <T> toSubscriber(observable: Observable<GetMovie<T>>, subscriber: Subscriber<T>) {
 2 
 3         observable
 4 
 5                 .compose {
 6 
 7                     it.flatMap { result ->
 8 
 9                         if (result.count!! > 0)
10 
11                             createData(result.subjects)
12 
13                         else
14 
15                             Observable.error(Throwable(""))
16 
17                     }
18 
19                 }
20 
21                 .subscribeOn(Schedulers.io())
22 
23                 .unsubscribeOn(Schedulers.io())
24 
25                 .observeOn(AndroidSchedulers.mainThread())
26 
27                 .doOnError {}
28 
29                 .subscribe(subscriber)
30 
31     }

可以看到这里我们使用了两个RxJava的操作符分别是compose与flatMap,经过flatMap的转换返回一个新的被观察者绑定的数据便是subjects

 1 private fun <T> createData(data: T): Observable<T> {
 2 
 3         return Observable.create { subscriber ->
 4 
 5             try {
 6 
 7                 subscriber.onNext(data)
 8 
 9                 subscriber.onCompleted()
10 
11             } catch (e: Exception) {
12 
13                 subscriber.onError(e)
14 
15             }
16 
17         }
18 
19     }

最后,业务逻辑中这样调用:

 1  HttpMethod.httpMethod.getTopMovie(1,1,object :Subscriber<List<Subject>>(){
 2 
 3             override fun onNext(t: List<Subject>?) {
 4 
 5                 sample_text.text =t?.get(0)?.originalTitle
 6 
 7             }
 8 
 9             override fun onCompleted() {
10 
11             }
12 
13             override fun onError(e: Throwable?) {
14 
15             }
16 
17         })

 

传入参数及Subscriber,经过compose转换在onNext中得到List<Subject>。

至此对RxJava与Retrofit的封装告一段落了,通过compose操作符,我们可以随心的去操作数据流,以得到我们想要的数据,并且还有其他丰富的操作符,例如repeatWhen,retryWhen ,doOnError,delay等等实用的方法,在稍后会和大家做进一步介绍。

编辑:邓秉帝海

发布:2019-01-24 06:54:48

当前文章:http://leetaemin.cn/array/mjylm5n5vo.html

拼多多货源哪里找 微创打码平台 找对象哪个网站好 2018如何利用网络赚钱 2018用电脑怎么赚钱 53兼职网官网登录 58办公室兼职 app挂机广告赚钱软件

73375 73321 59957 92748 71134 3989899684 83733 48969

我要说两句: (0人参与)

发布