現實開發中,一個頁面不多隻有一個請求的,通常都有多個請求,有的須要串行,有的須要並行,使用傳統的方法,若是有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,向它致敬!!!!