RxJava 之 操作符

什麼是RxJava

  • RxJava 就是異步
  • RxJava 的異步實現,是通過一種擴展的觀察者模式來實現的。
  • 一個響應式的編程框架

什麼是RxJava 操作符?

可以說,操作符是RxJava 最強大的武器
操作符一個重要的理念就是,使數據始終處於流上。
RxJava的操作符是幹什麼用的呢?簡單理解,就是用於進行轉換結合過濾數學運算等操作的方法。

看看之前的Demo看看我們是如何輸出Hello world 的

Observable.just("Hello, world!")  
    .subscribe(new Action1<String>() {  
        @Override  
        public void call(String s) {  
              System.out.println(s);  
        }  
    });

好了,現在如果要求你將輸入內容按照大寫輸出,你會怎麼改呢?首先看看RxJava的做法:

        Observable.just("hello world")
                .map(new Func1<String, String>() {

                    @Override
                    public String call(String s) {
                        return s.toUpperCase();
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(MainActivity.class.getSimpleName(), "onNext--->" + s);
                        Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
                    }
                });

你也許會不服,覺得在Subscribe的call裏面修改不一樣可以嗎?

好,再來,如果要求你將輸入內容的截取部分內容輸出,同時又不需要轉換成大寫了,我們用RxJava實現:

        Observable.just("hello world")
//                .map(new Func1<String, String>() {
//
//                    @Override
//                    public String call(String s) {
//                        return s.toUpperCase();
//                    }
//                })
                .map(new Func1<String, String>() {

                    @Override
                    public String call(String s) {
                        return s.substring(6);
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(MainActivity.class.getSimpleName(), "onNext--->" + s);
                        Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
                    }
                });

map

上面用到的map()操作符就是用於變換Observable對象的,map操作符返回一個Observable對象,這樣就可以實現鏈式調用。

你可能稍微有點動心了,需求的改變,不會導致 Observable 和 Subscribe 實現方式的更改,這應該是我們最希望的模式吧。

需修變更,最好的不去更新之前測試過的代碼。

這裏的例子很簡單,我們就算去修改Subscribe的實現,主要是call方法實現,你也不會覺得有多麼困難,但是實際開發中可不是這麼簡單。

create & just

create 也是操作符,用於創建一個包含 onNext()、onComplete和onError() 事件的Observable對象。
just 就是用來創建只發出一個事件就結束的Observable對象

RxJava操作符初探

from

Observable.from()方法,它接收一個集合作爲輸入,然後每次輸出一個元素給subscriber。當有多個輸入,那麼就類似隊列,一個一個來的時候,需要通過循環輸出,而from剛好可以實現這個功能

ArrayList<String> datas = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            datas.add("item_" + i);
        }

Observable.from(datas)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(MainActivity.class.getSimpleName(), "call---->" + s);
                    }
                });

是不是很神奇,沒有for循環,居然完成了list的遍歷輸出。

這裏我們的宗旨還是不要去改變Subscribe的實現。

flatMap

Observable.flatMap()接收一個Observable的輸出作爲輸入,同時輸出另外一個Observable。

ArrayList<String> datas = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            datas.add("item_" + i);
        }

       Observable.just(datas)
                .flatMap(new Func1<ArrayList<String>, Observable<String>>() {
                    @Override
                    public Observable<String> call(ArrayList<String> strings) {
                        return Observable.from(strings);
                    }
                })
                .map(new Func1<String, Integer>() {
                    @Override
                    public Integer call(String s) {
                        return s.hashCode();
                    }
                })
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer Integer) {
                        Log.e(MainActivity.class.getSimpleName(), "call---->" + Integer);
                    }
                });

這裏我們從just操作符得到Observable,經過flatMap再次得到一個Observable,並且最後通過map操作符輸出了我們列表中每一個數據的hash值。

注意在這段代碼裏,我們的Observable和Subscribe並沒有任何對數據的操作 ,通過RxJava強大的操作符我們就完成了從
List—->String—->Integer 的數據類型轉換輸出。

filter

這個單詞很好理解,過濾,這個操作符的意義也就是過濾。

Observable.from(datas)
                .filter(new Func1<String, Boolean>() {
                    @Override
                    public Boolean call(String s) {
                        return !s.equals("item_5");
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(MainActivity.class.getSimpleName(), "call---->" + s);
                    }
                });

日誌輸出

filter

這裏我們可以看到,item_5 的內容已經被過濾掉了。

take

take()輸出最多指定數量的結果。

這個應該很好理解了,就是指定了最多輸出的項數,相當於是限定了for循環的次數。

doOnNext

doOnNext()允許我們在每次輸出一個元素之前做一些額外的事情。

Observable.from(datas)
                .filter(new Func1<String, Boolean>() {
                    @Override
                    public Boolean call(String s) {
                        return !s.equals("item_5");
                    }
                })
                .take(5)
                .doOnNext(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        s=s.substring(0,3).toUpperCase();
                        Log.e(MainActivity.class.getSimpleName(), "call---->" + s);
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(MainActivity.class.getSimpleName(), "call---->" + s);
                    }
                });

這裏我們只輸出了列表裏的前5項,並且在每一個項輸出之前,截取其前3個字符,並轉換爲大寫輸出。

Range

range(n,m) Range操作符根據出入的初始值n和數目m發射一系列大於等於n的m個值

Observable
                .range(12, 10)
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.e(MainActivity.class.getSimpleName(), "the integer is " + integer);
                    }
                });

輸出如下:

range

這個操作符很好理解 。

當然了,這裏的這些處理是很簡單的,但在實際業務邏輯中,這樣的流式操作數據是很有意義,且很方便的。至少,代碼在後期維護起來會方便許多。

RxJava包含了大量的操作符,真的非常多。而且從上面列舉的這幾個操作符可以看出,各種操作符可以無限制的組合使用,所以說,操作符是RxJava最爲強大的武器之一,更有意思的是,操作符是可以自定義的,這樣的套路,想想都覺得刺激,但這些都是需要花費大量精力去學習的。

感興趣的同學 可以看看RxMarbles,這裏通過生動的圖片對各種不同種類的操作符進行了描述。

其實,上面所有操作符的功能,在Java 語言中,我們用for,if,else等許多行謎之縮進的語句實現是完全沒有問題的,但是那樣的代碼,就算是寫代碼的人,後期維護起來也是不容易的。

而我們使用RxJava的操作符的組合排列,秉承着使數據始終處於流上的觀念,代碼被分解成了一系列的片段,這樣最起碼維護和更新的時候會方便許多。

好了,關於操作符的內容就到這裏。


發佈了47 篇原創文章 · 獲贊 23 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章