Rxjava

Rxjava原理介紹

  • Rxjava原理 基於 一種擴展的觀察者模式
  • Rxjava的擴展觀察者模式中有4個角色:

img

角色 作用 類比
被觀察者(Observable) 產生事件 顧客
觀察者(Observer) 接收事件,並給出響應動作 廚房
訂閱(Subscribe) 連接 被觀察者 & 觀察者 服務員
事件(Event) 被觀察者 & 觀察者 溝通的載體 菜式

img

RxJava

        // 1.創建被觀察者Observable對象
        Observable <Integer> observable = Observable.create(new ObservableOnSubscribe <Integer>(){ 
          // create()是RxJava最基本的創造事件序列的方法
          //此處傳入了一個OnSubscribe對象參數
          //當Observable被訂閱時,OnSubscribe的call()方法會自動被調用,即事件序列就會依照設定依次被觸發
          //即觀察者會依次調用對應事件的複寫方法從而響應事件
          //從而實現被觀察者調用了觀察者的回調方法&由被觀察者向觀察者的事件傳遞,即        觀察者模式// 2.在複寫的subscribe()裏定義需要發送的事件            @Override             public void subscribe(ObservableEmitter <Integer> emitter)throws Exception {                 //通過ObservableEmitter類對象產生事件並通知觀察者                // ObservableEmitter類介紹                    // a。定義:事件發射器







                    // b. 作用:定義需要發送的事件 & 向觀察者發送事件
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        });

<--擴展:RxJava 提供了其他方法用於 創建被觀察者對象Observable -->
// 方法1:just(T...):直接將傳入的參數依次發送出來
  Observable observable = Observable.just("A", "B", "C");
  // 將會依次調用:
  // onNext("A");
  // onNext("B");
  // onNext("C");
  // onCompleted();

// 方法2:from(T[]) / from(Iterable<? extends T>) : 將傳入的數組 / Iterable 拆分成具體對象後,依次發送出來
  String[] words = {"A", "B", "C"};
  Observable observable = Observable.from(words);
  // 將會依次調用:











```java

<--方式1:採用Observer 接口 -->
        // 1. 創建觀察者 (Observer )對象
        Observer<Integer> observer = new Observer<Integer>() {
        // 2. 創建對象時通過對應複寫對應事件方法 從而 響應對應事件

            // 觀察者接收事件前,默認最先調用複寫 onSubscribe()
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "開始採用subscribe連接");
            }

            // 當被觀察者生產Next事件 & 觀察者接收到時,會調用該複寫方法 進行響應
            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "對Next事件作出響應" + value);
            }

            // 當被觀察者生產Error事件& 觀察者接收到時,會調用該複寫方法 進行響應
            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "對Error事件作出響應");
            }

            // 當被觀察者生產Complete事件& 觀察者接收到時,會調用該複寫方法 進行響應
            @Override
            public void onComplete() {
                Log.d(TAG, "對Complete事件作出響應");
            }
        };

<--方式2:採用Subscriber 抽象類 -->
// 說明:Subscriber類 = RxJava 內置的一個實現了 Observer 的抽象類,對 Observer 接口進行了擴展

// 1. 創建觀察者 (Observer )對象
Subscriber<String> subscriber = new Subscriber<Integer>() {

// 2. 創建對象時通過對應複寫對應事件方法 從而 響應對應事件
            // 觀察者接收事件前,默認最先調用複寫 onSubscribe()
            @Override
            public void onSubscribe(Subscription s) {
                Log.d(TAG, "開始採用subscribe連接");
            }

            // 當被觀察者生產Next事件 & 觀察者接收到時,會調用該複寫方法 進行響應
            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "對Next事件作出響應" + value);
            }

            //當被觀察者生產錯誤事件與觀察者接收到時,會調用該複寫方法進行響應
            @覆蓋
            公共無效的onError(Throwable的發送){ 
                Log.d(TAG, “對錯誤事件作出響應”); 
            }             //當被觀察者生產完成事件&觀察者接收到時,會調用該複寫方法進行響應            @覆蓋            公共無效的onComplete(){                 Log.d(TAG, “對完整的事件作出響應”);             }         }; < - 特別注意:2種方法的區別,即訂閱者抽象類與觀察者接口的區別 - > //相同點:二者基本使用方式完全一致(實質上,在RxJava的訂閱過程中,Observer總是會議先被轉換成Subscriber再使用)//不同點:Subscriber抽象類對觀察者接口進行了擴展,新增了兩個方法:    // 1. onStart():在還未響應事件前調用,用於做一些初始化工作    // 2. unsubscribe():用於取消訂閱。在該方法被調用後,觀察者將不再接收和響應事件














    // 調用該方法前,先使用 isUnsubscribed() 判斷狀態,確定被觀察者Observable是否還持有觀察者Subscriber的引用,如果引用不能及時釋放,就會出現內存泄露






<div class="se-preview-section-delimiter"></div>
通過訂閱(Subscribe)連接觀察者和被觀察者
observable.subscribe(observer);
 // 或者 observable.subscribe(subscriber);
<-- Observable.subscribe(Subscriber) 的內部實現 -->

public Subscription subscribe(Subscriber subscriber) {
    subscriber.onStart();
    // 步驟1中 觀察者  subscriber抽象類複寫的方法,用於初始化工作
    onSubscribe.call(subscriber);
    // 通過該調用,從而回調觀察者中的對應方法從而響應被觀察者生產的事件
    // 從而實現被觀察者調用了觀察者的回調方法 & 由被觀察者向觀察者的事件傳遞,即觀察者模式
    // 同時也看出:Observable只是生產事件,真正的發送事件是在它被訂閱的時候,即當 subscribe() 方法執行時
}






<div class="se-preview-section-delimiter"></div>
// RxJava的鏈式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
        // 1. 創建被觀察者 & 生產事件
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        }).subscribe(new Observer<Integer>() {
            // 2. 通過通過訂閱(subscribe)連接觀察者和被觀察者
            // 3. 創建觀察者 & 定義響應事件的行爲
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG,“開始採用subscribe連接”);             ()
            ; 
//默認最先調用複寫的onSubscribe()            @             Override public void onNext(Integer value){                 Log.d(TAG,“對Next事件”+ value +“作出響應”);             }             @Override             public void onError(Throwable e){                 Log.d(TAG,“對錯誤事件作出響應”);             }             @Override             public void onComplete(){                 Log.d(TAG,“對完成事件作出響應”);             }         });     } } 注:整體方法調用順序:觀察者.onSubscribe()>被觀察者.subscribe()>觀察者.onNext()>觀察者。

























 方式1:分步驟實現

**步驟1:加入依賴**





<div class="se-preview-section-delimiter"></div>

```java
 compile 'io.reactivex.rxjava2:rxjava:2.0.1'
 compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

步驟2:直接在MainActivity.java中實現下述步驟

  1. 創建被觀察者 (Observable )& 生產事件
  2. 創建觀察者 (Observer )並 定義響應事件的行爲
  3. 通過訂閱(Subscribe)連接觀察者和被觀察者
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "Rxjava";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);



// 步驟1:創建被觀察者 Observable & 生產事件
// 即 顧客入飯店 - 坐下餐桌 - 點菜

        //  1. 創建被觀察者 Observable 對象
        Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
            // 2. 在複寫的subscribe()裏定義需要發送的事件
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                // 通過 ObservableEmitter類對象產生事件並通知觀察者
                // ObservableEmitter類介紹
                    // a. 定義:事件發射器
                    // b. 作用:定義需要發送的事件 & 向觀察者發送事件
                emitter.onNext(1); 
                emitter.onNext(2); 
                emitter.onNext(3); 
                emitter.onComplete(); 
            } 
        }); //步驟2:創建觀察者Observer並定義響應事件行爲//即開廚房 - 確定對應菜式        Observer <Integer> observer = new Observer <Integer>(){             //通過複寫對應方法來響應被觀察者            @覆寫            public void onSubscribe(Disposable d){                 Log.d(TAG,“開始採用subscribe連接”);             ()            ; //默認最先調用複寫的onSubscribe()            @             Override public void onNext(Integer value){                 Log.d(TAG,“對Next事件”+ value +“作出響應”);

















            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "對Error事件作出響應");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "對Complete事件作出響應");
            }
        };


        // 步驟3:通過訂閱(subscribe)連接觀察者和被觀察者
        // 即 顧客找到服務員 - 點菜 - 服務員下單到廚房 - 廚房烹調
        observable.subscribe(observer);
  • 測試結果

img

方式2:基於事件流的鏈式調用方式

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "Rxjava";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

// RxJava的流式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
        // 1. 創建被觀察者 & 生產事件
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        }).subscribe(new Observer<Integer>() {
            // 2. 通過通過訂閱(subscribe)連接觀察者和被觀察者
            // 3. 創建觀察者 & 定義響應事件的行爲
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "開始採用subscribe連接");
            }
            // 默認最先調用複寫的 onSubscribe()

            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "對Next事件"+ value +"作出響應"  );
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "對Error事件作出響應");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "對Complete事件作出響應");
            }

        });
    }
}

觀察者 Observer的subscribe()具備多個重載的方法

  public final Disposable subscribe() {}
    // 表示觀察者不對被觀察者發送的事件作出任何響應(但被觀察者還是可以繼續發送事件)

    public final Disposable subscribe(Consumer<? super T> onNext) {}
    // 表示觀察者只對被觀察者發送的Next事件作出響應
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {} 
    // 表示觀察者只對被觀察者發送的Next事件 & Error事件作出響應

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
    // 表示觀察者只對被觀察者發送的Next事件、Error事件 & Complete事件作出響應

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
    // 表示觀察者只對被觀察者發送的Next事件、Error事件 、Complete事件 & onSubscribe事件作出響應

    public final void subscribe(Observer<? super T> observer) {}
    // 表示觀察者對被觀察者發送的任何事件都作出響應

變換操作符

img

Map()

  • 作用
    對 被觀察者發送的每1個事件都通過 指定的函數 處理,從而變換成另外一種事件

即, 將被觀察者發送的事件轉換爲任意的類型事件。

img

 // 採用RxJava基於事件流的鏈式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {

            // 1. 被觀察者發送事件 = 參數爲整型 = 1、2、3
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);

            }
            // 2. 使用Map變換操作符中的Function函數對被觀察者發送的事件進行統一變換:整型變換成字符串類型
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "使用 Map變換操作符 將事件" + integer +"的參數從 整型"+integer + " 變換成 字符串類型" + integer ;
            }
        }).subscribe(new Consumer<String>() {

            // 3. 觀察者接收事件時,是接收到變換後的事件 = 字符串類型
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });

  • 測試結果

img

從上面可以看出,map() 將參數中的 Integer 類型對象轉換成一個 String類型 對象後返回,同時,事件的參數類型也由 Integer 類型變成了 String 類型

FlatMap()

  • 作用:將被觀察者發送的事件序列進行 拆分 & 單獨轉換,再合併成一個新的事件序列,最後再進行發送
  • 原理

    1. 爲事件序列中每個事件都創建一個 Observable 對象;
    2. 將對每個 原始事件 轉換後的 新事件 都放入到對應 Observable對象;
    3. 將新建的每個Observable 都合併到一個 新建的、總的Observable 對象;
    4. 新建的、總的Observable 對象 將 新合併的事件序列 發送給觀察者(Observer

https://upload-images.jianshu.io/upload_images/944365-a6f852c071db2f15.png

// 採用RxJava基於事件流的鏈式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
            }

            // 採用flatMap()變換操作符
        }).flatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer integer) throws Exception {
                final List<String> list = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    list.add("我是事件 " + integer + "拆分後的子事件" + i);
                    // 通過flatMap中將被觀察者生產的事件序列先進行拆分,再將每個事件轉換爲一個新的發送三個String事件
                    // 最終合併,再發送給被觀察者
                }
                return Observable.fromIterable(list);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });

  • 測試結果

img

注:新合併生成的事件序列順序是無序的,即 與舊序列發送事件的順序無關

ConcatMap()

  • 作用:類似FlatMap()操作符
  • FlatMap()的 區別在於:拆分 & 重新合併生成的事件序列 的順序 = 被觀察者舊序列生產的順序
  • 原理

https://upload-images.jianshu.io/upload_images/944365-f4340f283e5a954d.png

// 採用RxJava基於事件流的鏈式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
            }

            // 採用concatMap()變換操作符
        }).concatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer integer) throws Exception {
                final List<String> list = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    list.add("我是事件 " + integer + "拆分後的子事件" + i);
                    // 通過concatMap中將被觀察者生產的事件序列先進行拆分,再將每個事件轉換爲一個新的發送三個String事件
                    // 最終合併,再發送給被觀察者
                }
                return Observable.fromIterable(list);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });

img

注:新合併生成的事件序列順序是有序的,即 嚴格按照舊序列發送事件的順序

Buffer()

  • 作用
    定期從 被觀察者(Obervable)需要發送的事件中 獲取一定數量的事件 & 放到緩存區中,最終發送
  • 原理

img

  • 應用場景

緩存被觀察者發送的事件

// 被觀察者 需要發送5個數字
        Observable.just(1, 2, 3, 4, 5)
                .buffer(3, 1) // 設置緩存區大小 & 步長
                                    // 緩存區大小 = 每次從被觀察者中獲取的事件數量
                                    // 步長 = 每次獲取新事件的數量
                .subscribe(new Observer<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }
                    @Override
                    public void onNext(List<Integer> stringList) {
                        //
                        Log.d(TAG, " 緩存區裏的事件數量 = " +  stringList.size());
                        for (Integer value : stringList) {
                            Log.d(TAG, " 事件 = " + value);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "對Error事件作出響應" );
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "對Complete事件作出響應");
                    }
                });

  • 測試結果

img

  • 過程解釋

下面,我將通過一個圖來解釋Buffer()原理 & 整個例子的結果

https://upload-images.jianshu.io/upload_images/944365-33a49ffd2ec60794.png

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