RxJava查漏補缺

RxJava概念

標準中的觀察者設計模式,一個被觀察者,多個觀察者,多次註冊。
RxJava是改裝的觀察者設計模式,一個訂閱(註冊) 一個觀察者。
一旦滿足 起點 和 終點 這樣的需求,都可以使用RxJava來實現。

RxJava創建型操作符

create:使用者自己發射事件
just 內部自己發射的,單一對象
fromArray 內部自己發射的,數集對象
empty:內部自己發射的 ,下游默認是Object,無法發出有值事件,只會發射 onComplete
range:內部自己發射的,start 1 累加 count 5 最後結果:1 2 3 4 5

RxJava變換型操作符

1.map 把上一層Int Int變換String 觀察者String類型。
2.flatMap 把上一層Int Int變換ObservableSource{還可以再次發射多次事件} 觀察者String類型。 不排序的
3.concatMap 把上一層Int Int變換ObservableSource{還可以再次發射多次事件} 觀察者Bitmap類型。 排序的
4.groupBy 把上一層Int Int變換String(高端配置電腦) 觀察者GroupedObservable類型 {key=“高端”, 細節再包裹一層}
5.buffer 100個事件 Integer .buffer(20) 觀察者List==五個集合

groupBy

	   // 上游
      Observable.just(6000, 7000, 8000, 9000, 10000, 14000)

       // 變換
      .groupBy(new Function<Integer, String>() {
          @Override
          public String apply(Integer integer) throws Exception {
              return integer > 8000 ? "高端配置電腦" : "中端配置電腦"; // 分組
          }
      })
      // 使用groupBy下游是 有標準的
      .subscribe(new Consumer<GroupedObservable<String, Integer>>() {
          @Override
          public void accept(final GroupedObservable<String, Integer> groupedObservable) throws Exception {
              Log.d(TAG, "accept: " + groupedObservable.getKey());
              // 以上還不能把信息給打印全面,只是拿到了,分組的key

              // 輸出細節,還需要再包裹一層
              // 細節 GroupedObservable 被觀察者
              groupedObservable.subscribe(new Consumer<Integer>() {
                  @Override
                  public void accept(Integer integer) throws Exception {
                      Log.d(TAG, "accept: 類別:" + groupedObservable.getKey() + "  價格:" + integer);
                  }
              });
          }
      });

輸出結果

accept: 中端配置電腦
accept: 類別:中端配置電腦  價格:6000
accept: 類別:中端配置電腦  價格:7000
accept: 類別:中端配置電腦  價格:8000
accept: 高端配置電腦
accept: 類別:高端配置電腦  價格:9000
accept: 類別:高端配置電腦  價格:10000
accept: 類別:高端配置電腦  價格:14000

buffer:很多的數據,不想全部一起發射出去,分批次,先緩存到Buffer

		// 上游
       Observable.create(new ObservableOnSubscribe<Integer>() {
           @Override
           public void subscribe(ObservableEmitter<Integer> e) throws Exception {
               for (int i = 0; i < 100; i++) {
                   e.onNext(i);
               }
               e.onComplete();
           }
       })
       // 變換 buffer
       .buffer(20)
       .subscribe(new Consumer<List<Integer>>() {
           @Override
           public void accept(List<Integer> integer) throws Exception {
               Log.d(TAG, "accept: " + integer);
           }
       });

輸出結果

accept: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
accept: [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
accept: [40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
accept: [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
accept: [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

RxJava過濾型操作符

1.filter 如果是false全部都發射給下游,如果是true,全部都不發射給下游。
2.take :只有在定時器運行基礎上 加入take過濾操作符,纔有take過濾操作符的價值。
3.distinct 過濾重複事件。
4.elementAt 指定發射事件內容,如果無法指定,有默認的事件。

elementAt

		// 上游
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("九陰真經");
                e.onNext("九陽真經");
                e.onNext("易筋經");
                e.onNext("神照經");
                e.onComplete();
            }
        })
        // 過濾操作符
        .elementAt(2, "默認經") // 指定下標輸出 事件
        // 訂閱
        .subscribe(new Consumer<String>() { // 下游
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "accept: " + s);
            }
        });

輸出結果

accept: 易筋經

RxJava條件型操作符

All: 如同 if 那樣的功能 :全部爲true,纔是true,只要有一個爲false,就是false.
contains 是否包含
any 全部爲 false,纔是false, 只要有一個爲true,就是true
如果使用了條件操作符,下一層,接收的類型 就是條件類型(Boolean)

RxJava合併型操作符

兩個或者多個 被觀察者 合併。
1.startWait,concatWith :先創建被觀察者,然後再組合其他的被觀察者,然後再訂閱
2.concat/merge/zip:直接合並多個被觀察者,然後訂閱
細節:
a:startWait 先執行 startWait括號裏面的被觀察者
b:concatWait 後執行 concatWait括號裏面的被觀察者
c:concat 是按照順序依次執行 最多四個被觀察者進行合併
d:merge 並列執行的,(演示並列的執行,所以學了intervalRange) 最多四個被觀察者進行合併
e:zip 需要對應關係 需要對應,如果不對應,會被忽略的, 最多9個被觀察者 進行合併

RxJava異常處理操作符

RxJava中是不標準的throw new IllegalAccessError(“我要報錯了”);RxJava標準的e.onError(XXX);

1.onErrorReturn最先攔截到e.onError並且可以給下游返回一個 標識400, throw new XXX 攔截不到,整個程序奔潰
2.onErrorResumeNext最先攔截到e.onError並且可以給下游返回一個 被觀察者(還可以再次發送), throw new XXX 攔截不到,整個程序奔潰
3.onExceptionResumeNext 能在發生異常的時候,扭轉乾坤,能夠處理 throw new XXX,可以真正的讓App不奔潰
4.retry return false; 代表不去重試 return true; 不停的重試, 可指定重試次數

RxJava線程切換

1.異步線程區域
Schedulers.io() :代表io流操作,網絡操作,文件流,耗時操作
Schedulers.newThread() : 比較常規的,普普通通
Schedulers.computation() : 代表CPU 大量計算 所需要的線程
2.AndroidSchedulers.mainThread() : 專門爲Android main線程量身定做的

3.給上游分配多次,只會在第一次切換,後面的不切換了(忽略)
4.給下游分配多次,每次都會去切換
5.如果不配置異步線程,上游發一次,下游接收一次,上游發一次,下游接收一次,上游發一次,下游接收一次
6.配置好異步線程,就是異步的表現(線程搶奪),可能上游先發送N個,然後下游再接收N個,然後上游再發Y個,下游再接收Z個…
7.傳統下載圖片的寫法,代碼容易東一塊西一塊,RxJava下載圖片,基於事件流編程,一條鏈子,起點和終點

		// RxJava如果不配置,默認就是主線程main
        // 上游
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                Log.d(TAG, "上游 subscribe: " + Thread.currentThread().getName());

                e.onNext("");
            }
        }).subscribeOn(Schedulers.io()) // todo 給上游配置異步線程    // 給上游分配多次,只會在第一次切換,後面的不切換了
                .subscribeOn(AndroidSchedulers.mainThread()) // 被忽略
                .subscribeOn(AndroidSchedulers.mainThread()) // 被忽略
                .subscribeOn(AndroidSchedulers.mainThread()) // 被忽略
                .subscribeOn(AndroidSchedulers.mainThread()) // 被忽略
                // result: io 異步線程

          .observeOn(AndroidSchedulers.mainThread()) // todo 給下游配置 安卓主線程    // 給下游分配多次,每次都會去切換
                .observeOn(AndroidSchedulers.mainThread()) // 切換一次線程
                .observeOn(AndroidSchedulers.mainThread()) // 切換一次線程
                .observeOn(AndroidSchedulers.mainThread()) // 切換一次線程
                .observeOn(Schedulers.io()) // 切換一次線程
                // result: io 異步線程

                .subscribe(new Consumer<String>() { // 下游簡化版
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, "下游 subscribe: " + Thread.currentThread().getName());
            }
        });

RxJava背壓模式

背壓模式的由來:
RxJava1.X的時候,還沒有背壓模式, 我們的上游不停的發射,我們的下游處理不過來,就會照成內存泄漏
RxJava2.X之後,增加背壓模式,Flowable(解決背壓)

什麼時候用Observable<—>Observer, 什麼使用Flowable<—>Subscriber ?

答:發射的事件,大量的事件(1000個),並且考慮到下游處理不過來,就需要使用Flowable

BackpressureStrategy.ERROR // todo 上游不停的發射大量事件,下游阻塞了 處理不過來,放入緩存池,如果池子滿了,就會拋出異常
BackpressureStrategy.BUFFER // todo  上游不停的發射大量事件,下游阻塞了 處理不過來,放入緩存池,”等待“下游來接收事件處理
BackpressureStrategy.DROP //  todo   上游不停的發射大量事件,下游阻塞了 處理不過來,放入緩存池,如果池子滿了,就會把後面發射的事件丟棄
 // (1 ~ 5000  池子滿了4000,   4001 ~ 5000丟棄)
BackpressureStrategy.LATEST // todo 上游不停的發射大量事件,下游阻塞了 處理不過來,只存儲 128個事件

同步的,沒有執行Subscription s.request(), 當上遊發射1,下游無法處理(沒有執行s.request()),會拋出異常
異步的,上游不停的發射,可以在r02方法中,s.request(10) 可以取出來給 下游接收事件處理的
一旦下游處理了一次上游的事件,緩存池 - 1

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