編輯:關於Android編程
switchIfEmpty(Observable emptyObservable)操作符從字面意思上就很好理解,就是當為空的時候跳轉到emptyObservable。
那麼如何理解當為空的時候. 下面將會使用實際案例解釋這個switchIfEmpty的使用方法。
假如我們的app裡有加載文章列表功能,要求加載的邏輯如下:加載文章的的時候,先從本地加載,如果本地存在就是用本地的數據,如果不存在從網絡獲取。
下面是業務代碼:
//從本地數據獲取文章列表 getArticlesObservable(pageIndex, pageSize, categoryId) //本地不存在,請求api .switchIfEmpty(articleApi.getArticlesByCategoryId(pageIndex + "", pageSize + "", categoryId + "") .compose(this.handlerResult()) .flatMap(new Func1 >() { @Override public Observable call(RespArticlePaginate respArticlePaginate) { if (respArticlePaginate != null && respArticlePaginate.getList() != null) { try { articleDao.insertOrReplaceInTx(respArticlePaginate.getList()); } catch (Exception e) { e.printStackTrace(); } } return Observable.just(respArticlePaginate); } })) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(createSubscriber(ID_ARTICLE_LIST)))
這裡的 createSubscriber 封裝了Subscriber對成功、失敗的數據處理,然後統一把數據推給上一層,就不用每個地方都寫下面相同的模板代碼了:
observable.subscribe(new Action1() { @Override public void call(RespArticlePaginate respArticlePaginate) { //success data } }, new Action1 () { @Override public void call(Throwable throwable) { // error data } })
那麼createSubscriber是如何實現的,先看subscribe方法源碼 如下:
public final Subscription subscribe(final Action1 onNext, final Action1onError) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); } if (onError == null) { throw new IllegalArgumentException("onError can not be null"); } Action0 onCompleted = Actions.empty(); return subscribe(new ActionSubscriber (onNext, onError, onCompleted)); }
很簡單,他是直接new了一個ActionSubscriber,然後把我們以前在代碼裡寫的各個回調(onNext、onError、onComplete)當做參數傳遞進去。那麼我們的createSubscriber也可以模擬它的實現:
/** * 處理結果(分發結果) 封裝 * * @param id 區分業務類型 */ protectedActionSubscriber createSubscriber(final int id) { //因為我們只關心onNext和onError Action0 onCompleted = Actions.empty(); return new ActionSubscriber (new Action1 () { @Override public void call(T t) { pushSuccessData(id, t); } }, new Action1 () { @Override public void call(Throwable throwable) { pushThrowable(id, throwable); } }, onCompleted); }
好了,言歸正傳,回到我們上面提到的需求。根據需求我們來分析下代碼:
getArticlesObservable方法用來從本地獲取文章列表,articleApi.getArticlesByCategoryId方法是用來當本地不存在的時候從網絡獲取。似乎這些代碼可以實現了我們上面提到的需求了。而且很簡潔。
實踐是檢驗真理的唯一標准,我們先運行下看看(本地環境是數據庫沒有文章列表)。
運行後,發現界面並沒有展示數據,通過debug返現,代碼執行了檢測本地緩存的邏輯,且本地找不到符合邏輯的數據,也就是說從本地找到的結果為空。但是沒有按照我們預想的是執行網絡請求。
先來看看查詢本地緩存的代碼是是什麼樣子。
Observable.create(new Observable.OnSubscribe
通過debug發現代碼走的邏輯是
if (as == null || as.isEmpty()) { subscriber.onNext(null); }
發送的是空,為什麼還是沒有走switchIfEmpty裡的邏輯呢?肯定是我們用的姿勢不對,先看看該該方法的說明:
/** * Returns an Observable that emits the items emitted by the source Observable or the items of an alternate * Observable if the source Observable is empty. * * * Scheduler: * {@code switchIfEmpty} does not operate by default on a particular {@link Scheduler}. * * * @param alternate * the alternate Observable to subscribe to if the source does not emit any items * @return an Observable that emits the items emitted by the source Observable or the items of an * alternate Observable if the source Observable is empty. * @since 1.1.0 */ public final Observable switchIfEmpty(Observablealternate) { return lift(new OperatorSwitchIfEmpty(alternate)); }
重點關注對參數Observablealternate的解釋:
the alternate Observable to subscribe to if the source does not emit any items
意思是如果原來的Observable沒有發射任何數據(emit any items),則使用alternate代替原來的Observable。
好,再看看我們的代碼邏輯:
if (as == null || as.isEmpty()) { subscriber.onNext(null); }
這段代碼不是沒有發射數據,而是發射了個空數據,也就是發射了null,所以這段代碼並不是沒有發射任何數據,所以為什麼不走網絡請求的邏輯。
知道原因就好解決了,加上個過濾就可以解決問題了:
.filter(new Func1() { @Override public Boolean call(RespArticlePaginate respArticlePaginate) { return respArticlePaginate != null; } })
1,通過switchIfEmpty可以做到一些邏輯判斷,當然實現類型的判斷本地緩存的,可以通過concat結合takeFirst操作符來實現,具體的可以看我以前的博客文章
2,上面通過Observable.create方式來包裝數據查詢,不是很優雅。下一篇博客介紹如何封裝RxJava,使得我們的代碼支持RxJava鏈式調用。
系統對四大組件的過程進行了很大程度的封裝,日常開發中並不需要了解底層的工作原理,那麼研究這些原理的意義在哪裡呢?如果你想在技術上更進一步,那麼了解一些系統的工作原理是十分
1.普通側滑效果圖: 思路:通過自定義View繼承HorizontalScrollView,然後重寫onMeasure(),onLayout(),onTouch
簡單介紹一下,現在的主流移動設備像Android、iPhone等都使用SQLite作為復雜數據的存儲引擎,在我們為移動設備開發應用程序時,也許就要使用到SQLite來存儲
最近在做項目,小組幾個回了家。界面暫時沒人做,用到自定義對話框只能臨時去學。現在把對話框的相關整理。 +