RxHttp 优雅的实现请求串行与并行

前言

现实开发中,一个页面不多只有一个请求的,通常都有多个请求,有的须要串行,有的须要并行,使用传统的方法,若是有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为咱们提供了异常捕获操做符,如:onErrorResumeNextonErrorReturn,做用就是出现异常了,咱们如何去补救它。若是你不了解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的mergeflatMap,就能够优雅的实现的Http请求的串行及并行。若是你对RxJava有必定的了解,还能够实现不少有意思的功能,好比:为单个请求设置超时、请求失败自动重试n次等等。

最后,一切功劳都要归功于RxJava的强大,感谢RxJava,向它致敬!!!!

相关文章
相关标签/搜索