Rxjava2(一)、基礎概念及使用

Android進階系列之第三方庫知識點整理。

知識點總結,整理也是學習的過程,如有錯誤,歡迎批評指出。

寫這篇文章的時候,Rxjava3已經出來了,二者差別不是特別大,所以還是基於Rxjava2進行總結,後續會花時間來總結Rxjava3的一些改變。

基礎概念

1、什麼是Rx

ReactiveX是Reactive Extensions的縮寫,一般簡寫爲Rx,最初是LINQ的一個擴展,Rx是由由微軟開發並開源的一個編程模型,目標是提供一致的編程接口,幫助開發者更方便的處理異步數據流,Rx庫支持很多語言,而 Rxjava 是Rx庫基於Java語言提供的函數庫。

官網顯示支持的語言列表:

2、觀察者模式

觀察者模式(Observer),又叫發佈-訂閱模式(Publish/Subscribe),定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並自動更新,觀察者模式屬於行爲型模式。

我需要打電話跟小明說他被戴綠帽這事,但是我又怕打電話過去他可能在忙,所以我直接給他發信息,讓他有時間了再給我回電話,這樣,當小明有時間了可能就會給我回電話,他給我回電話,我再含着淚的告訴他要堅強。

在上面這個例子中,小明就是被觀察者,我是觀察者,我發短信告訴他有時間回我電話這個操作就是訂閱,這樣我跟他有了依賴關係,當他有時間後,就會回我帶電話,我這邊響應式的執行後續的操作。

3、響應式(Reactive Programming)編程

一般來說,編程就是爲了處理問題,解決問題就可以有不同的視角和思路,其中具有普適性的模式就會歸結一種編程思想,我們常說的面向對象,面向過程都是一種編程思想。

響應式編程是一種通過異步和數據流來構建事務關係的編程模式

這裏麪包含的兩個核心概念:

異步:不需要等待處理完成便立刻返回,通過回調將處理結果帶回。能提高吞吐量,提高性能和效率。

數據流:就是按照時間線的事件序列,任何東西都可以看做是一個stream。在這個基礎上通過函數來過濾(filter)、選擇(select)、變換(transform)、結合(combine)這些stream。通過定義事件處理器,來異步捕獲感興趣的stream,即監聽(訂閱)stream,也叫就是註冊觀察者。

再對比我們前面的觀察者模式看,觀察者模式中被觀察者觀察者之間通過訂閱產生依賴,訂閱這層關係相當於在二者之前挖了一道水渠,被觀察者是上游,觀察者是下游,這樣被觀察者發生改變時候,會將數據流源源不斷的發送到產生依賴關係的觀察者,通常觀察者被觀察者是處於同一個線程中,但是響應式編程重點在異步上,即上游和下游可以在不同的線程中工作。

我們可以看一下官網的動圖:

4、Rxjava概念及簡單使用

Rxjava採用了響應式編程模式,它在觀察者模式基礎上進行擴展,方便我們的異步操作,觀察者被觀察者產生訂閱關係後,被觀察者將數據流發送給觀察者的時候,Rxjava提供了豐富的操作符來對數據流進行過濾(filter)、選擇(select)、變換(transform)、結合(combine)等等操作,然後再將處理後的數據發送給觀察者,又由於其特別棒的鏈式調用,讓邏輯在很複雜的情況下,也能很清晰的通過代碼表達出來。

我們先引入rxjava

implementation "io.reactivex.rxjava2:rxjava:2.2.8"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

直接先來一個簡單的例子:

  // 通過 Observable 創建一個被觀察者
  Observable mObservable = Observable.create(new ObservableOnSubscribe() {
         @Override
         public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        });
        
        // 通過Observer創建一個觀察者
        Observer mObserver = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                LogUtil.d(TAG + "--onSubscribe");
            }

            @Override
            public void onNext(Integer o) {
                LogUtil.d(TAG + "--onNext  o=" + o);
            }

            @Override
            public void onError(Throwable e) {
                LogUtil.d(TAG + "--onError");
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--onComplete");
            }
        };
        // 產生訂閱關係
        mObservable.subscribe(mObserver);

再看看Rxjava強大的鏈式調用:

Observable.create(new ObservableOnSubscribe() {
       @Override
       public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
            // 這裏直接通過subscribe將二者鏈式調用起來
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                LogUtil.d(TAG + "--Observer--onSubscribe");
            }

            @Override
            public void onNext(Integer o) {
                LogUtil.d(TAG + "--Observer--onNext  o=" + o);
            }

            @Override
            public void onError(Throwable e) {
                LogUtil.d(TAG + "--Observer--onError");
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--Observer--onComplete");
            }
        });

我們前面說,RxJava是拓展於觀察者模式的響應式編程,所以在Rxjava中,就有觀察者被觀察者以及二者通過訂閱產生的依賴關係。

通過上面代碼,可以看到:

被觀察者 ——————> Observable

觀察者 ——————> Observer

訂閱關係:Observable ————> subscribe <———— Observer

在上游的 Observable (被觀察者)中通過 emitter(發射器)就可以不斷地給下游的 Observer (觀察者)傳送數據流,我們在上游發射了 1、2、3還有發射了一個 onComplete 事件。

我們通過日誌可以看到,在下游的 Observer (觀察者)成功的接收到了上游發送的數字1、2、3包括通過調用 onComplete()方法來接收上游發送的 onComplete 事件。

通過上面一個簡單的例子,我們可以總結出以下幾點

4.1、解耦

我們可以看到被觀察者和觀察者都是獨立存在的。

Observable(被觀察者):

  // 通過 Observable 創建一個被觀察者
  Observable mObservable = Observable.create(new ObservableOnSubscribe() {
         @Override
         public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        });

Observer(觀察者):

 // 通過Observer創建一個觀察者
        Observer mObserver = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                LogUtil.d(TAG + "--onSubscribe");
            }

            @Override
            public void onNext(Integer o) {
                LogUtil.d(TAG + "--onNext  o=" + o);
            }

            @Override
            public void onError(Throwable e) {
                LogUtil.d(TAG + "--onError");
            }

            @Override
            public void onComplete() {
                LogUtil.d(TAG + "--onComplete");
            }
        };

可以看到,二者各自獨立存在,各幹各的事,只是通過 subscribe 來建立依賴關係,這樣的話,可以很好地實現代碼的複用,比如我們可以創建多個Observer(觀察者),和Observable(被觀察者)之間通過訂閱建立依賴關係後,就能實現Observable(被觀察者)發送的數據流被多個Observer(觀察者)接收。

4.2、數據流轉換(操作符的使用)

第二、Observable(被觀察者)通過 emitter(發射器)將數據以流的形式發送給Observer(觀察者),前面講了,既然是以流的形式,那我們是不是可以在觀察者接收數據之前,對數據進行處理呢?答案是肯定的,這也是Rxjava的強大之一,它可以通過各種操作符來對數據進行處理,我們先講一個簡單的來。

這裏只是簡單的演示一些Rxjava對數據流的操作,後面會具體講操作符,圖片中可以看到,我們被觀察者明明發射的是一個int型的數值100,但是通過map操作符進行數據流進行轉換後,下游的消費者接收到的竟然是String的,這裏只是一個小Demo,在Rxjava中,還有各種很強大的操作符來對數據進行各種變態式的處理。

上游被觀察者Observable發射數據,下游除了使用Observer來接收數據外,還可以使用消費者Consumer來接收數據,可以看Consumer只有一個accept方法。

先貼一下Rxjava強大的操作符列表,是不是很多?不要被嚇到,越多所以我們可以越方便的對數據流進行各種各樣的操作,這個後面會單獨再講解。

4.3、線程切換

我們前面說了,Rxjava能更好的異步操作,我們先用上面的例子打印一下他們當前所在的線程情況。

結果:

可以到,統一戰線的都在主線程,我們來看看,怎麼實現異步。

同樣是那個例子,我們添加了下面這兩個代碼

subscribeOn(Schedulers.io())
observeOn(AndroidSchedulers.mainThread())

subscribeOn : 指定上游執行的線程

observeOn:指定觀察者或者消費者執行線程

結果:

代碼中,我們指定上游在io線程,而下游在主線程執行,就這麼簡單的兩行代碼,就實現了線程切換,實現了異步操作,爽不爽?

當然,我們不光可以指定io線程,Schedulers還提供了其他的線程供我們選擇。

我們簡單看一個Single線程的源碼:

是不是很熟悉?就是通過線程池來創建了一個單線程,其他類似,都是通過線程池來創建,您可以簡單去分析一下,當然,如果你對線程池還不熟悉的話,這篇 多線程(三)、線程池 ThreadPoolExecutor 知識點總結 可能適合你看看。

總結

Rxjava的東西還挺多的,這篇先簡單的走了一遍Rxjava的基礎概念還有簡單的使用,關於Rxjava裏面還有其他的觀察者模式的創建,背壓,各種操作符的使用、實戰等等騷操作,下篇繼續。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章