Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> RxJava switchIfEmpty操作符實現Android檢查本地緩存邏輯判斷

RxJava switchIfEmpty操作符實現Android檢查本地緩存邏輯判斷

編輯:關於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 Action1 onError) {
        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 區分業務類型
     */

    protected  ActionSubscriber 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. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved