现实开发中,一个页面不多只有一个请求的,通常都有多个请求,有的须要串行,有的须要并行,使用传统的方法,若是有n个接口,咱们就要设置n个接口回调,若是是串行的话,还须要在当前接口成功或失败的地方,调用下个一个请求,一个接着一个,真的是要逼死强迫症患者,并且代码可读性很是的差,新人来了每每要看上半天,很差维护且容易出错。java
本文使用RxHttp请求框架做为案例演示,若是你不了解RxHttp,请查看30秒上手新一代Http请求神器RxHttpreact
请允许我再唠两句:RxHttp从4月中旬开始推广,在你们都对新的Http请求框架学不动或者懒得学的状况下,RxHttp依然收获了一大波粉丝,目前在Github上一经有415颗星,其中git
RxHttp 一条链发送请求,新一代Http请求神器github
Android 史上最优雅的实现文件上传、下载及进度的监听微信
这两篇文章更是获得了获得「玉刚说」及「刘望舒」微信公众号独家原创发布,我想,这也是对RxHttp的一种确定,欢迎你们体验RxHttp,它优雅的写法及强大的功能,相信你必定会爱上它。框架
gradle依赖post
implementation 'com.rxjava.rxhttp:rxhttp:1.1.5'
annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:1.1.5' //注解处理器,生成RxHttp类
implementation 'com.rxjava.rxlife:rxlife:1.0.9' //页面销毁,关闭请求,非必须
// if you use kotlin
kapt 'com.rxjava.rxhttp:rxhttp-compiler:1.1.5'
复制代码
接下来,咱们正是开始。gradle
如今不少页面是这样的,上面是Banner条,Banner条下面是数据列表(假设是学生列表),这样就涉及到两个接口,一个是获取Banner条数据,另外一是获取学生列表数据,这两个接口没有任何关系,因此咱们能够并行去实现this
//Banner 的Observable对象
Observable<Banner> bannerObservable = RxHttp.get("http://...")
.asObject(Banner.class);
//学生的Observable对象
Observable<List<Student>> studentObservable = RxHttp.get("http://...")
.asList(Student.class);
//这里使用RxJava组合符中的merge操做符,将两个被观察者合并为一个
Observable.merge(bannerObservable, studentObservable)
.as(RxLife.asOnMain(this)) //感知生命周期,自动关闭请求
.subscribe(o -> {
//请求成功,回调2次,一次是Banner数据,一次Student列表
if (o instanceof Banner) {
//获取到banner数据
} else if (o instanceof List) {
//获取到学生列表数据
}
}, throwable -> {
//出现异常
}, () -> {
//2个请求执行完毕,开始更新UI
});
复制代码
能够看到,咱们首先经过RxHttp类拿到Banner和Student的两个Observable对象,而后经过merge操做符,将两个Observable对象合并为一个,并订阅观察者,这样就能在onNext回调中拿到Banner和Student数据,并在onComplete回调中更新UI。spa
但是,这样就完了吗?熟悉RxJava的同窗应该知道,RxJava在出现异常后而且回调到onError接口时,就会中止工做,那么若是Banner接口先出现异常,岂不是收不到Student信息了?是的,那么,咱们应该如何去处理呢,其实很简单,RxJava为咱们提供了异常捕获操做符,如:onErrorResumeNext
和onErrorReturn
,做用就是出现异常了,咱们如何去补救它。若是你不了解RxJava错误处理机制,请查看RxJava错误处理详解。这里,咱们使用onErrorResumeNext操做符,代码以下
//Banner 的Observable对象
Observable<Banner> bannerObservable = RxHttp.get("http://...")
.asObject(Banner.class)
.onErrorResumeNext(Observable.empty()); //出现异常,发送一个空的Observable对象
//学生的Observable对象
Observable<List<Student>> studentObservable = RxHttp.get("http://...")
.asList(Student.class);
//这里使用RxJava组合符中的merge操做符,将两个被观察者合并为一个
Observable.merge(bannerObservable, studentObservable)
.as(RxLife.asOnMain(this)) //感知生命周期,自动关闭请求
.subscribe(o -> {
//请求成功,回调2次,一次是Banner数据,一次Student列表
if (o instanceof Banner) {
//获取到banner数据
} else if (o instanceof List) {
//获取到学生列表数据
}
}, throwable -> {
//出现异常
}, () -> {
//2个请求执行完毕,开始更新UI
});
复制代码
上面咱们只加了onErrorResumeNext(Observable.empty())
这一行代码,Observable.empty()是一个不会发射任何事件的Observable对象。因此,这个时候若是Banner的Observable出现异常,就不会发射任何事件,Student 的Observable对象即可继续执行,只是在onNext回调中,就只能收到一次Student的回调(请求成功的话),而且随后执行onComplete回调更新UI,这样就能保证即便Banner接口出错了,咱们依然能够正常现实学生列表数据。说的抽象一点就是保证A接口不影响B接口,可是B能够影响A接口,若是要保证A、B两个接口互不影响,分别对A、B接口处理异常便可,若是有3个、4个甚至更多的请求,可使用Observable.mergeArray
操做符。
接下来,看看咱们串行,假设咱们有这样一个需求,须要在注册完成后当即去登陆,这种状况下,就只能串行去实现,在这,咱们使用RxJava的flatMap
这个操做符去实现
flatMap
RxHttp.postForm("http://...") //发送注册请求
.add("userName", "zhangsan")
.add("password", "123456")
.asObject(Register.class)
.flatMap((io.reactivex.functions.Function<Register, ObservableSource<User>>) register -> {
//注册成功,拿到注册信息去登陆,并返回User对象
return RxHttp.get("http://...") //发送登陆请求
.add("userId", register.getUserId())
.add("password", register.getPassword())
.subscribeOnCurrent() //当前线程发送登陆请求
.asObject(User.class);
})
.as(RxLife.asOnMain(this)) //感知生命周期,自动关闭请求
.subscribe(user -> {
//注册而且登陆成功,拿到用户信息
}, throwable -> {
//出现异常,注册失败或者登陆失败
});
复制代码
注:
RxHttp中的asXXX
系列方法,内部会默认开启IO线程执行Http请求,因此咱们在发送单个请求时,无需指定请求执行线程;然而在多个请求串行时,为提高效率,咱们但愿一个线程能够执行多个请求,故咱们须要使用subscribeOnCurrent
方法指定请求在当前线程执行。
能够看到,这里咱们使用flatMap
操做符,当注册成功,就会走到flatMap内部去登陆,登陆成功就会拿到User对象并回调观察者。
看完你会发现,RxHttp作到了与RxJava的无缝链接,使用asXXX
系列方法,就能够拿到一个Observable<T>
对象,随后再结合RxJava的merge
、flatMap
,就能够优雅的实现的Http请求的串行及并行。若是你对RxJava有必定的了解,还能够实现不少有意思的功能,好比:为单个请求设置超时、请求失败自动重试n次等等。
最后,一切功劳都要归功于RxJava的强大,感谢RxJava,向它致敬!!!!