RxHttp 一條鏈發送請求之多請求串行與並行 (五)

前言

現實開發中,一個頁面很少只有一個請求的,一般都有多個請求,有的需要串行,有的需要並行,使用傳統的方法,如果有n個接口,我們就要設置n個接口回調,如果是串行的話,還需要在當前接口成功或失敗的地方,調用下個一個請求,一個接着一個,真的是要逼死強迫症患者,而且代碼可讀性非常的差,新人來了往往要看上半天,不好維護且容易出錯。

本文使用RxHttp請求框架作爲案例演示,如果你不瞭解RxHttp,請查看30秒上手新一代Http請求神器RxHttp

請容許我再嘮兩句:RxHttp從4月中旬開始推廣,在大家都對新的Http請求框架學不動或者懶得學的情況下,RxHttp依然收穫了一大波粉絲,目前在Github上一經有415顆星,其中

RxHttp 一條鏈發送請求,新一代Http請求神器

Android 史上最優雅的實現文件上傳、下載及進度的監聽

這兩篇文章更是得到了得到「玉剛說」及「劉望舒」微信公衆號獨家原創發佈,我想,這也是對RxHttp的一種肯定,歡迎大家體驗RxHttp,它優雅的寫法及強大的功能,相信你一定會愛上它。

gradle依賴

   implementation 'com.rxjava.rxhttp:rxhttp:1.0.9'
   annotationProcessor 'com.rxjava.rxhttp:rxhttp-compiler:1.0.9' //註解處理器,生成RxHttp類
   implementation 'com.rxjava.rxlife:rxlife:1.0.7'  //頁面銷燬,關閉請求,非必須

   // if you use kotlin
   kapt 'com.rxjava.rxhttp:rxhttp-compiler:1.0.9'

接下來,我們正是開始。

並行

現在很多頁面是這樣的,上面是Banner條,Banner條下面是數據列表(假設是學生列表),這樣就涉及到兩個接口,一個是獲取Banner條數據,另一是獲取學生列表數據,這兩個接口沒有任何關係,所以我們可以並行去實現

//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。

可是,這樣就完了嗎?熟悉RxJava的同學應該知道,RxJava在出現異常後並且回調到onError接口時,就會停止工作,那麼如果Banner接口先出現異常,豈不是收不到Student信息了?是的,那麼,我們應該如何去處理呢,其實很簡單,RxJava爲我們提供了異常捕獲操作符,如:onErrorResumeNextonErrorReturn,作用就是出現異常了,我們如何去補救它。在這,我們使用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,向它致敬!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章