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,向它致敬!!!!

相關文章
相關標籤/搜索