RxJava應(yīng)用場景——if 和 else

在項(xiàng)目中應(yīng)用RxJava時(shí),遇到了這樣的使用場景:
模擬從服務(wù)器返回了一個(gè)列表。

    private Observable<List<String>> getData() {
        List<String> stringList = new ArrayList<>();
        return Observable.just(stringList);
    }

我在處理數(shù)據(jù)時(shí),想判斷一下這個(gè)list是不是空,如果不為空,顯示數(shù)據(jù),如果為空,給用戶一個(gè)沒有數(shù)據(jù)的提示。也就是我們常用的if和else操作。于是我是這樣寫的:

        Observable<List<String>> observable = getData();
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(@NonNull List<String> strings) throws Exception {
                        if (strings != null && strings.size() > 0) {
                            // 顯示數(shù)據(jù)
                        } else {
                            // 顯示沒有數(shù)據(jù)的提示
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        // 錯(cuò)誤處理
                    }
                });

Filter

可是我覺得這樣不夠優(yōu)雅不夠RxJava,所以我想到了Filter操作符,能不能用它來幫我完成呢?于是我修改了一下我的代碼。

        Observable<List<String>> observable = getData();
        observable.filter(new Predicate<List<String>>() {
                    @Override
                    public boolean test(@NonNull List<String> strings) throws Exception {
                        return strings != null && strings.size() > 0;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(@NonNull List<String> strings) throws Exception {
                        // 顯示數(shù)據(jù)
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        // 錯(cuò)誤處理
                    }
                });

來看一下Filter操作符的官方圖示。

filter

emit only those items from an Observable that pass a predicate test

它會(huì)按照我們給它的條件進(jìn)行過濾,在本例中,只有當(dāng)服務(wù)器返回的list不為null并且有數(shù)據(jù)時(shí),
才會(huì)發(fā)出。這樣的話,可以滿足我有數(shù)據(jù)時(shí)顯示數(shù)據(jù)的需求,但是沒有數(shù)據(jù)時(shí)顯示提示怎么辦呢?

GroupBy

然后我想到了GroupBy這個(gè)操作符。

先看一下官方的圖示吧。

groupBy

divide an Observable into a set of Observables that each emit a different subset of items from the original Observable

它可以把一個(gè)Observable按照一定的條件分成多個(gè)Observable,在本例中,是否可以分成有數(shù)據(jù)和沒數(shù)據(jù)兩種呢?

我又修改了一下代碼。

      Observable<List<String>> observable = getData();
      observable.groupBy(new Function<List<String>, Boolean>() {
                    @Override
                    public Boolean apply(@NonNull List<String> strings) throws Exception {
                        return strings != null && strings.size() > 0;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<GroupedObservable<Boolean, List<String>>>() {
                    @Override
                    public void accept(@NonNull GroupedObservable<Boolean, List<String>> groupedObservable) throws Exception {
                        if (groupedObservable.getKey()) {
                            groupedObservable.subscribe(new Consumer<List<String>>() {
                                @Override
                                public void accept(@NonNull List<String> strings) throws Exception {
                                    // 顯示數(shù)據(jù)
                                }
                            });
                        } else {
                            groupedObservable.subscribe(new Consumer<List<String>>() {
                                @Override
                                public void accept(@NonNull List<String> strings) throws Exception {
                                    // 顯示沒有數(shù)據(jù)的提示
                                }
                            });
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        // 錯(cuò)誤處理
                    }
                });

關(guān)鍵在于,有一個(gè)新的GroupedObservable,它有一個(gè)getKey()方法,得到的這個(gè)key就是我們在groupBy操作符中返回的類型,本例中使用的是Boolean類型,根據(jù)不同的業(yè)務(wù)需要,也可以返回Integer或者String等等。

然后在Subscribe的時(shí)候,根據(jù)不同的key值,分為了不同的Observable,滿足了我的需求。

SwitchIfEmpty

最近是實(shí)際使用中,發(fā)現(xiàn)如果使用GroupBy操作符,會(huì)比較復(fù)雜,特別是會(huì)生成了一個(gè)新的groupedObservable。
那么有沒有更好的方法來實(shí)現(xiàn)if-else呢?
來看看另一個(gè)操作符吧,defaultIfEmpty。

defaultIfEmpty
        Observable<List<String>> observable = getData();
        observable
                .filter(new Predicate<List<String>>() {
                    @Override
                    public boolean test(@NonNull List<String> strings) throws Exception {
                        return strings != null && strings.size() > 0;
                    }
                })
                .defaultIfEmpty(new ArrayList<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(@NonNull List<String> strings) throws Exception {
                        // 顯示數(shù)據(jù)
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        // 錯(cuò)誤處理
                    }
                });

當(dāng)filter操作符判斷不符合條件不發(fā)射時(shí),可以通過defaultIfEmpty操作符添加一個(gè)默認(rèn)的值。不過好像能做的事情不是很多。
所以我又換了一個(gè)switchIfEmpty操作符。

        Observable<List<String>> observable = getData();
        observable
                .filter(new Predicate<List<String>>() {
                    @Override
                    public boolean test(@NonNull List<String> strings) throws Exception {
                        return strings != null && strings.size() > 0;
                    }
                })
                .switchIfEmpty(new Observable<List<String>>() {
                    @Override
                    protected void subscribeActual(Observer<? super List<String>> observer) {
                        List<String> newList = new ArrayList<>();
                        newList.add("new");
                        observer.onNext(newList);
                        observer.onComplete();
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(@NonNull List<String> strings) throws Exception {
                        // 顯示數(shù)據(jù)
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(@NonNull Throwable throwable) throws Exception {
                        // 錯(cuò)誤處理
                    }
                });

效果是一樣的,也是添加了默認(rèn)值,不過能干的事情好像更多了一些。實(shí)際上看一下源碼,發(fā)現(xiàn)其實(shí)差不太多。

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Observable<T> defaultIfEmpty(T defaultItem) {
        ObjectHelper.requireNonNull(defaultItem, "defaultItem is null");
        return switchIfEmpty(just(defaultItem));
    }

只是調(diào)用了switchIfEmpty(just(defaultItem))而已。

不過我發(fā)現(xiàn)了一個(gè)問題,如果我判斷一個(gè)list是不是空,使用filter和switchIfEmpty結(jié)合起來是可以滿足的,但是有些情況會(huì)有問題,看下面這個(gè)例子:

      Observable.just(1, 2, 3, 4, 5)
                .filter(new Predicate<Integer>() {
                    @Override
                    public boolean test(Integer integer) throws Exception {
                        return integer % 2 == 0;
                    }
                })
                .switchIfEmpty(new Observable<Integer>() {
                    @Override
                    protected void subscribeActual(Observer<? super Integer> observer) {
                        observer.onNext(-1);
                        observer.onComplete();
                    }
                })
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer integer) throws Exception {
                        System.out.println("integer = [" + integer + "]");
                    }
                });

按照我的設(shè)想,應(yīng)該是-1,2,-1,4,-1這么個(gè)順序,然而結(jié)果卻是2,4。這是為什么呢?
原來如果連續(xù)發(fā)射1,2,3,4,5的時(shí)候,filter操作符會(huì)過濾掉1,3,5,發(fā)射2和4,所以并不為空,所以switchIfEmpty就不會(huì)得到執(zhí)行。比如我們只發(fā)射1,會(huì)被filter過濾掉,然后調(diào)用switchIfEmpty,得到-1;如果我們發(fā)射的是1和2,會(huì)得到2;如果發(fā)射1和3,也只會(huì)得到-1,而不是-1和-1,因?yàn)閟witchIfEmpty只會(huì)調(diào)用一次。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符。對于擴(kuò)展包,由于使用率較低,如有需求,請讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 46,232評論 8 93
  • 創(chuàng)建操作 用于創(chuàng)建Observable的操作符Create通過調(diào)用觀察者的方法從頭創(chuàng)建一個(gè)ObservableEm...
    rkua閱讀 1,962評論 0 1
  • RxJava正在Android開發(fā)者中變的越來越流行。唯一的問題就是上手不容易,尤其是大部分人之前都是使用命令式編...
    劉啟敏閱讀 2,017評論 1 7
  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的,對什么是操作、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,994評論 0 10
  • 前言 按照官方的分類,操作符大致分為以下幾種: Creating Observables(Observable的創(chuàng)...
    小玉1991閱讀 1,127評論 0 1

友情鏈接更多精彩內(nèi)容