以前在github開源過一個網絡庫RxEasyHttp,這是一款基於RxJava2+Retrofit2實現簡單易用的網絡請求框架。在這裏對網絡庫的用法就不作過多介紹,感興趣的能夠去了解下。在使用過程當中一些網友反饋不知道怎麼結合Rxjava2來實現一些場景需求,但願可以寫一遍文章介紹下。終於抽出時間來對與Rxjava2在實際場景使用的一些案例作個簡單的總結和介紹。不知道怎麼使用,主要是對RxEasyHttp有個誤區,RxEasyHttp不只是支持採用鏈式調用一點到底方便使用,同時也支持返回Observable
的用法,拿到了Observable
天然就能夠很好的利用Rxjava操做符了來實現各類強大的功能。本文主要是講RxEasyHttp與Rxjava2怎麼結合的,也不會Rxjava2的操做符深刻講解,否則就脫離了本文的重心!廢話很少說了,一塊兒來看看是如何使用的。php
在頁面網絡接口請求中,不是但願立馬請求,而是須要延遲指定的時間後再去請求。
延遲請求:利用RxJava的timer
操做符。
timer:主要做用就是建立一個Observable
,它在一個給定的延遲後發射一個特殊的值,只是延遲發送一次並不會按照週期執行。timer()
源碼以下:java
public static Observable<Long> timer(long delay, TimeUnit unit) { return timer(delay, unit, Schedulers.computation()); }
能夠看到採用timer()
返回的是Observable<Long>
,而網絡請求返回的Observable
並非Observable<Long>
,如何將這兩個Observable
關聯起來,就須要採用另一個操做符flatMap()
,簡單理解就是flatMap
使用一個指定的函數對原始Observable發射的每一項數據進行相應的變換操做。flatMap詳細做用不作過多介紹。
例如:延遲5秒請求git
//延遲5s請求 Observable.timer(5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<SkinTestResult>>() { @Override public ObservableSource<SkinTestResult> apply(@NonNull Long aLong) throws Exception { //延遲結束開始執行網絡請求 Observable<SkinTestResult> observable = EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult") .timeStamp(true) .execute(SkinTestResult.class); return observable; } }).subscribe(new BaseSubscriber<SkinTestResult>() { @Override protected void onStart() { } @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull SkinTestResult skinTestResult) { Log.i("test", "=====" + skinTestResult.toString()); } }); //在不須要輪詢的時候,取消輪詢 //EasyHttp.cancelSubscription(polldisposable);
- timer在這裏做用延遲5s結束時就會觸發網絡請求
- flatMap在這裏的做用就是將
timer
操做符返回的Observable<Long>
和網絡請求的Observable<SkinTestResult>
作轉換,在subscribe訂閱時返回的內容,咱們真正須要的SkinTestResult,而不是Long. 所以將Observable<Long>
變換成Observable<SkinTestResult>
輸出SkinTestResult,完美達到目的。
在項目中須要用到每隔5s刷新一次頁面或者拉取最新消息。輪詢器你們必定不陌生,開發中不管是Java的Timer+TimeTask , 仍是Android的Hanlder均可實現,如今介紹另外一種簡單的實現方式。
無限輪詢:利用RxJava的Interval
操做符。
interval:建立一個按固定時間間隔發射整數序列的Observable,它是按照週期執行的。源碼以下(只展現相關的兩個方法):github
public static Observable<Long> interval(long initialDelay, long period, TimeUnit unit) { return interval(initialDelay, period, unit, Schedulers.computation()); } public static Observable<Long> interval(long period, TimeUnit unit) { return interval(period, period, unit, Schedulers.computation()); }
能夠看到採用interval()
返回的是Observable<Long>
,而網絡請求返回的Observable
並非Observable<Long>
,如何將這兩個Observable
關聯起來,就須要採用另一個操做符flatMap()
,簡單理解就是flatMap使用一個指定的函數對原始Observable發射的每一項數據之行相應的變換操做。flatMap詳細做用不作過多介紹(同上場景一)。
例如:間隔5s輪詢一次ajax
//本身根據須要選擇合適的interval方法 Disposable polldisposable = Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<Content>>() { @Override public ObservableSource<Content> apply(@NonNull Long aLong) throws Exception { return EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); } }).subscribeWith(new BaseSubscriber<Content>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull Content content) { showToast(content.toString()); } }); //在不須要輪詢的時候,取消輪詢 //EasyHttp.cancelSubscription(polldisposable);
- interval在這裏做用每隔5s結束時就會觸發網絡請求
- 注意
interval(0, 5, TimeUnit.SECONDS)
和interval(5, TimeUnit.SECONDS)
的區別,本身根據須要選擇合適的interval方法。
interval(0,5, TimeUnit.SECONDS)
:3個參數,第一個參數表示初始化延時多久開始請求,這裏用0表示不延時直接請求,第二個參數表示間隔多久輪詢一次,這裏表示間隔5s,第三個表示設置的時間單位。interval(5, TimeUnit.SECONDS)
:2個參數,其中的這個5就表示,初始延時5秒開始執行請求,輪詢也是5s,第二個表示設置的時間單位,從上面提供的interval()
源碼能夠看出。json
flatMap
在這裏的做用就是將interval
的Observable<Long>
和網絡請求的Observable<Content>
作轉換,輸出Content,而不是Long.
這個和無限輪詢用法基本同樣,只是多了輪詢的次數限制條件,不是一直無限的輪詢下去。
輪詢次數:利用RxJava的intervalRange
或者take
操做符。
intervalRange:以一個例子說明可能更清楚,intervalRange(0,3,0,5, TimeUnit.SECONDS)
表示從0開始輸出3個數據,延遲0秒執行,每隔5秒執行一次。
take:表示只取前n項。這裏用take和interval操做符聯合使用,因爲一旦interval計時開始除了解綁就沒法中止,使用take操做符就簡單不少了,它的意思是隻釋放前n項,事後Observable流就自動終止。
例如:只輪詢3次api
int count = 3;//輪詢3次 //方式一:採用intervalRange //Observable.intervalRange(0,count,0,5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<Content>>() { //方式一:採用take countdisposable = Observable.interval(0, 5, TimeUnit.SECONDS).take(count).flatMap(new Function<Long, ObservableSource<Content>>() { @Override public ObservableSource<Content> apply(@NonNull Long aLong) throws Exception { return EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); } }).subscribeWith(new BaseSubscriber<Content>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull Content content) { showToast(content.toString()); } }); //在不須要輪詢的時候,取消輪詢 //EasyHttp.cancelSubscription(polldisposable);
條件輪詢和限定次數輪詢比較像,都是起達到目的後終止輪詢。好比一個網絡請求一直在輪詢執行,直到獲取到了想要的內容後就終止掉輪詢。
條件輪詢:利用RxJava的takeUntil
操做符。
takeUntil:使用一個標誌Observable是否發射數據來判斷,當標誌Observable沒有發射數據時,正常發射數據,而一旦標誌Observable發射過了數據則後面的數據都會被丟棄。
例如:輪詢請求中若是返回的內容字符串中包含「示」就終止輪詢數組
Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<Content>>() { @Override public ObservableSource<Content> apply(@NonNull Long aLong) throws Exception { return EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); } }).takeUntil(new Predicate<Content>() { @Override public boolean test(@NonNull Content content) throws Exception { //若是條件知足,就會終止輪詢,這裏邏輯能夠本身寫 //結果爲true,說明知足條件了,就不在輪詢了 return content.getOut().contains("示"); } }).subscribeWith(new BaseSubscriber<Content>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull Content content) { showToast(content.toString()); } }); //在不須要輪詢的時候,取消輪詢 //EasyHttp.cancelSubscription(polldisposable);
過濾輪詢主要是指在輪詢的過程當中對訂閱的內容作過濾,不是須要的內容就不會返回給訂閱者,可是它不會中斷輪詢。過濾輪詢也能夠理解成是無限輪詢加了一個過濾條件而已。
過濾輪詢:利用Rxjava的filter
操做符。
filter:是對源Observable產生的結果按照指定條件進行過濾,只有知足條件的結果纔會提交給訂閱者。
例如:返回的狀態碼若是是錯誤就不返回給訂閱者,不更新界面(只有保證每次請求成功才刷新界面),可是會繼續輪詢請求緩存
Disposable filterdisposable = Observable.interval(0, 5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<Content>>() { @Override public ObservableSource<Content> apply(@NonNull Long aLong) throws Exception { return EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); } }).filter(new Predicate<Content>() { @Override public boolean test(@NonNull Content content) throws Exception { //若是不知足條件就過濾該條輪詢數據,可是輪詢仍是一直執行 //ErrNo==0表示成功,若是不等於0就認爲失敗,content不會返回給訂閱者 return content.getErrNo() != 0; } }).subscribeWith(new BaseSubscriber<Content>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull Content content) { showToast(content.toString()); } }); //在不須要輪詢的時候,取消輪詢 //EasyHttp.cancelSubscription(polldisposable);
filter
操做符在這裏只是爲了舉列說明,是本身爲了講解定義了一個過濾輪詢的概念,不是說filter
只能在輪詢這裏使用,它是能夠和其它任何Rxjava操做符配合使用。- 切記
takeUntil
和filter
的區別,takeUntil
找到本身想要的數據後就結束了流,再也不執行任何操做。filter
發現不符合條件的不會給訂閱者,只有符合條件的纔給訂閱者,發現不符合的,不會中斷操做。
在開發中因爲請求網絡數據頻繁,每每後面一個請求的參數是前面一個請求的結果,因而常常須要在前面一個請求的響應中去發送第二個請求,從而形成「請求嵌套」的問題。若是層次比較多,代碼可讀性和效率都是問題。嵌套請求:利用RxJava的flatMap
操做符。
flatMap:是一個Observable的操做符,接受一個Func1閉包,這個閉包的第一個函數是待操做的上一個數據流中的數據類型,第二個是這個flatMap操做完成後返回的數據類型的被封裝的Observable。說白了就是將一個多級數列「拍扁」成了一個一級數列。
例如:網絡請求獲取到token後,把token當成另外一個接口的參數,一個接口依賴另外一個接口。網絡
//第一個網絡請求獲取到token Observable<AuthModel> login = EasyHttp.post(ComParamContact.Login.PATH) .params(ComParamContact.Login.ACCOUNT, "186****4275") .params(ComParamContact.Login.PASSWORD, MD5.encrypt4login("123456", AppConstant.APP_SECRET)) .sign(true) .timeStamp(true).execute(AuthModel.class); login.flatMap(new Function<AuthModel, ObservableSource<SkinTestResult>>() { @Override public ObservableSource<SkinTestResult> apply(@NonNull AuthModel authModel) throws Exception { //獲取到的token,給到第二個網絡當參數。第二個網絡開始請求 return EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult") .params("accessToken", authModel.getAccessToken())//這個地方只是舉例,並不必定是須要accessToken .timeStamp(true) .execute(SkinTestResult.class); } }).subscribe(new ProgressSubscriber<SkinTestResult>(this, mProgressDialog) { @Override public void onError(ApiException e) { super.onError(e); showToast(e.getMessage()); } @Override public void onNext(SkinTestResult skinTestResult) { showToast(skinTestResult.toString()); } });
本例中只是展現了2個接口的嵌套請求,flatMap實際上是能夠支持嵌套不少個接口請求
zip合併請求就是指當一個頁面有多個不一樣的數據來源,既就是有多個不一樣的網絡請求接口,等待這些全部的接口都請求完成後才返回給訂閱者,刷新界面等操做。
zip:使用一個函數組合多個Observable發射的數據集合,而後再發射這個結果.
例如:一個頁面有3個不一樣數據來源的網絡請求接口,等待所有請求完成後才返回
Observable<ResultBean> mobileObservable = EasyHttp.get("http://apis.juhe.cn/mobile/get") .params("phone", "18688994275") .params("dtype", "json") .params("key", "5682c1f44a7f486e40f9720d6c97ffe4") .execute(new CallClazzProxy<TestApiResult1<ResultBean>, ResultBean>(ResultBean.class) { }); Observable<Content> searchObservable = EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); Observable<List<SectionItem>> listObservable = EasyHttp.get("http://news-at.zhihu.com/api/3/sections") .execute(new CallClazzProxy<TestApiResult5<List<SectionItem>>, List<SectionItem>>(new TypeToken<List<SectionItem>>() { }.getType()) { }); //new Function3最後一個參數這裏用的是List<Object>,表示將3個返回的結果,放在同一個集合最終一次性返回, 你也能夠指定返回其它你須要的數據類型 並不必定是List<Object> //假如這三個接口返回的都是TestBean,那麼就能夠直接用具體的List<TestBean>,不須要用List<Object> Observable.zip(mobileObservable, searchObservable, listObservable, new Function3<ResultBean, Content, List<SectionItem>, List<Object>>() { @Override public List<Object> apply(@NonNull ResultBean resultbean, @NonNull Content content, @NonNull List<SectionItem> sectionItems) throws Exception { //將接收到的3個數據先暫存起來,一次性發給訂閱者 List list = new ArrayList(); list.add(resultbean); list.add(content); list.add(sectionItems); //這裏也能夠進行邏輯處理,處理成你本身須要的結果後,再返回。 return list; } }).subscribe(new BaseSubscriber<List<Object>>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull List<Object> objects) { showToast(objects.toString()); } });
1.zip的參數中前幾個參數都表示數據源ObservableSource
,最後一個參數new Function會輸出結果,前面若是有2個數據源就用Function2,3個數據源就用Function3.
2.Function的做用主要是會返回全部參與zip的結果內容,例如本例是有3個數據源(3個網絡接口請求對應的Observable),返回的內容是new Function3<ResultBean, Content, List<SectionItem>, List<Object>>
其中ResultBean, Content, List<SectionItem>
是三個網絡接口各自返回的內容。可是最後一個參數List<Object>
表示什麼呢?這一個就表示最終要給訂閱着subscribe
的內容,例如本例new BaseSubscriber<List<Object>>()
。這裏我是將返回的結果用一個List集合存起來,而後返回給訂閱者。最終想返回什麼是根據本身的業務邏輯需求而定,並不必定就是List<Object>
,切記!切記!切記!
剛纔講解了zip合併請求,這是合併請求的另外一種場景實現方式merge,必定要注意merge和zip的區別,雖然都是合併多個請求,可是是有區別的,請注意使用場景. 本例中利用Rxjava的merge
、mergeDelayError
操做符。
merge:將多個Observalbe發射的數據項,合併到一個Observable中再發射出去,可能會讓合併的Observable發射的數據交錯(concat操做符是鏈接不會出現交錯),若是在合併的途中出現錯誤,就會當即將錯誤提交給訂閱者,將終止合併後的Observable。
mergeDelayError:mergeDelayError
操做符相似於merge
操做符,惟一不一樣就是若是在合併途中出現錯誤,不會當即發射錯誤通知,而是保留錯誤直到合併後的Observable將全部的數據發射完成,此時纔會將onError提交給訂閱者。
例如:一個界面有兩個網絡接口請求
//這個請求故意延時5秒再發送->最後測試結果發現,並非searchObservable等待mobileObservable5秒後再發送,目的驗證無序的概念 Observable<ResultBean> mobileObservable = Observable.timer(5, TimeUnit.SECONDS).flatMap(new Function<Long, ObservableSource<ResultBean>>() { @Override public ObservableSource<ResultBean> apply(@NonNull Long aLong) throws Exception { return EasyHttp.get("http://apis.juhe.cn/mobile/get") .params("phone", "18688994275") .params("dtype", "json") .params("key", "5682c1f44a7f486e40f9720d6c97ffe4") .execute(new CallClazzProxy<TestApiResult1<ResultBean>, ResultBean>(ResultBean.class) { }); } }); Observable<Content> searchObservable = EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", "hello world") //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content>, Content>(Content.class) { }); //Observable.merge(mobileObservable,searchObservable).subscribe(new BaseSubscriber<Object>() { Observable.mergeDelayError(mobileObservable,searchObservable).subscribe(new BaseSubscriber<Object>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull Object object) { //爲何用Object接收,由於兩個接口請求返回的數據類型不是同樣的,若是是同樣的就用具體的對象接收就能夠了, // 再也不須要instanceof麻煩的判斷 if (object instanceof ResultBean) {//mobileObservable 返回的結果 //處理 ResultBean邏輯 } else if (object instanceof Content) { //處理 Content邏輯 } showToast(object.toString()); } });
其中提到一個概念:合併的Observable發射的數據交錯,也就是發射的數據無序,怎麼理解它呢?例如:代碼中merge(mobileObservable,searchObservable)
合併的mobileObservable和searchObservable,其中mobileObservable在前,並不表明訂閱的subscribe->onNext(@NonNull Object object)
就先返回來數據,也多是合併的searchObservable數據先返回回來。
延伸講解,剛纔講解了merge
操做符是無序的,若是想保證有序執行怎麼辦呢,採用Rxjava的concat
操做符
看完場景七和場景八:merge和zip的區別究竟是什麼呢?
merge和zip都是將多個Observalbe發射的數據項,合併到一個Observable中再發射出去。只是在發射的結果上有所不一樣。例若有3個網絡請求的Observalbe,zip是等待這3個請求都完成後才一塊兒返回,既onNext調用1次。merge是3個Observalbe分別返回,並且無序,既onNext調用3次,至關於把3個原本分散的網絡請求。寫在同一個地方合併起來執行。
merge、mergeDelayError都是合併,可是須要注意兩者區別。
- merge合併的請求,若是有一個接口報錯了,就立馬報錯,會終止整個流,另外的接口也不會請求。
- mergeDelayError合併的請求,若是有一個接口報錯了,會延遲錯誤處理,後面的接口會繼續執行沒有被中斷。
這裏主要是講解RxEasyHttp如何結合rxbinding庫compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
來使用。對rxbinding庫不瞭解的,能夠本身去學習一下,這裏不詳細介紹。在頁面請求中可能操做太快致使同一個網絡請求重複執行,這裏結合view來講明,點擊一個按鈕去請求網絡,點擊太快就會重複執行-界面防抖。
避免重複請求:利用Rxjavad的throttleFirst
操做符。
throttleFirst:會按期發射這個時間段裏源Observable發射的第一個數據。
例如:點擊按鈕去請求網絡,1s內避免點擊過快重複請求
RxView.clicks(view).throttleFirst(1, TimeUnit.SECONDS).flatMap(new Function<Object, ObservableSource<ResultBean>>() { @Override public ObservableSource<ResultBean> apply(@NonNull Object o) throws Exception { return EasyHttp.get("http://apis.juhe.cn/mobile/get") .params("phone", "18688994275") .params("dtype", "json") .params("key", "5682c1f44a7f486e40f9720d6c97ffe4") .execute(new CallClazzProxy<TestApiResult1<ResultBean>, ResultBean>(ResultBean.class) { }); } }).subscribe(new BaseSubscriber<ResultBean>() { @Override public void onError(ApiException e) { showToast(e.getMessage()); } @Override public void onNext(@NonNull ResultBean resultBean) { showToast(resultBean.toString()); } });
這裏也是主要講解RxEasyHttp如何結合rxbinding庫compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
來使用。對rxbinding庫不瞭解的,能夠本身去學習一下,這裏不介紹用法。像即時搜索功能,在輸入框中輸入內容,實時搜索結果展現。
減小頻繁的網絡請求:利用Rxjavad的debounce
操做符。
debounce:對源Observable每產生一個結果後,若是在規定的間隔時間內沒有別的結果產生,則把這個結果提交給訂閱者處理,不然忽略該結果。簡單的理解就是:當N個結點發生的時間太靠近(即發生的時間差小於設定的值T),debounce就會自動過濾掉前N-1個結點。
例如:即時搜索,避免每輸入(刪除)一個字就作一次請求,500毫秒才讓它去請求一次網絡,這樣能夠避免數據混亂,也優了app性能。
Disposable mDisposable = RxTextView.textChangeEvents(mEditText) .debounce(500, TimeUnit.MILLISECONDS).filter(new Predicate<TextViewTextChangeEvent>() { @Override public boolean test(@NonNull TextViewTextChangeEvent textViewTextChangeEvent) throws Exception { // 過濾,把輸入字符串長度爲0時過濾掉 String key = textViewTextChangeEvent.text().toString(); //這裏能夠對key進行過濾的判斷邏輯 return key.trim().length() > 0; } }).flatMap(new Function<TextViewTextChangeEvent, ObservableSource<Content2>>() { @Override public ObservableSource<Content2> apply(@NonNull TextViewTextChangeEvent textViewTextChangeEvent) throws Exception { String key = textViewTextChangeEvent.text().toString(); Log.d("test", String.format("Searching for: %s", textViewTextChangeEvent.text().toString())); return EasyHttp.get("/ajax.php") .baseUrl("http://fy.iciba.com") .params("a", "fy") .params("f", "auto") .params("t", "auto") .params("w", key) //採用代理 .execute(new CallClazzProxy<TestApiResult6<Content2>, Content2>(Content2.class) { }); } }).subscribeWith(new BaseSubscriber<Content2>() { @Override protected void onStart() { } @Override public void onError(ApiException e) { mTextView.setText(e.getMessage()); } @Override public void onNext(@NonNull Content2 content) { mTextView.setText(content.toString()); } }); //取消請求 //EasyHttp.cancelSubscription(mDisposable);
網絡數據緩存在RxEasyHttp網絡庫中已經封裝了,也就是開發者在使用網絡庫過程當中沒必要關心緩存具體的實現,經過RxEasyHttp庫文檔講解調用一些配置參數就能夠實現須要的緩存功能了。這裏主要講解的是不使用okhttp和Retrofit的緩存,而是介紹本身如何封裝緩存。RxEasyHttp網絡庫除了支持無緩存和默認的http緩存以外,又提供了其它6種場景緩存:
FIRSTREMOTE:先請求網絡,請求網絡失敗後再加載緩存
FIRSTCACHE:先加載緩存,緩存沒有再去請求網絡
ONLYREMOTE:僅加載網絡,但數據依然會被緩存
ONLYCACHE:只讀取緩存,緩存沒有會返回null
CACHEANDREMOTE:先使用緩存,無論是否存在,仍然請求網絡,CallBack會回調兩次.
CACHEANDREMOTEDISTINCT:先使用緩存,無論是否存在,仍然請求網絡,CallBack回調不必定是兩次,若是發現請求的網絡數據和緩存數據是同樣的,就不會再返回網絡的回調,既回調一次。不然不相同仍然會回調兩次。(目的是爲了防止數據沒有發生變化,也須要回調兩次致使界面無用的重複刷新)
若是對這部分源碼敢興趣的請查看RxEasyHttp源碼,因爲此部分涉及的知識點和內容比較多,篇幅問題,準備在下一篇文章中單獨介紹網絡數據緩存的各大場景實現,敬請期待!
到這裏幾大經常使用的RxEasyHttp網絡庫結合Rxjava2場景的例子已經介紹完了,也證實了RxEasyHttp網絡庫與Rxjava2是能夠完美結合的,在實際開發運用中的場景確定有不少種,例子是怎麼也舉不完的,須要靈活運用,如何寫這一個本身的場景呢,我以爲須要以下幾點:
flatMap
,Function
等操做;文章不免有疏漏之處,若是您有任何疑議,請反饋給我,謝謝!同時你們有與網絡相關更好更經常使用的場景請推薦給我,我會繼續完善。喜歡請點贊,謝謝!
對場景應用感興趣的小夥伴們能夠將Demo下載下來進行參考。
項目地址
https://github.com/zhou-you/RxEasyHttp
引用文字