RxJava 之 響應式編程

什麼是RxJava

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

響應式編程

在說響應式編程的概念之前,我們先從這篇文章《用工廠流水線的方式來理解 RxJava 的概念》理解一下RxJava的意義。這裏面說到的流水線的例子很確切,對於RxJava的響應式編程的思想是一個很好地類比。

從這個例子中,我們可以抽象出如下的流程

流水線——->操作工1—–>操作工2—–>…..操作工n–>產品經理

這也十分切合響應式編程的流程

Observable -> Operator 1 -> Operator 2 -> Operator 3 -> Subscriber

  • 如文中所講,產品經理很重要,推動了整個事件的方法,這一點也是RxJava 區別於傳統的觀察者模式的地方,沒有訂閱者(subscriber)時,Observeable 是不會發送事件的。

  • 作爲操作符,就像流水線上的工人,既要各司其職的完成各種工作,同時也要保證事件的處理永遠處於流水線上,這也是RxJava響應式編程的關鍵點,“流”的概念。

  • 在這裏,產品經理(Subscriber )也會完成一些重要的工作,但它希望流水線上的每個操作工(RxJava的操作符)也能完成一些重要的事情,能最大程度的確保產品經理已經完成的工作不需要再做修改。

下面結合一個簡單的例子說明一下,RxJava中響應式編程的優點。

RxJava 事件處理

假設,現有如下需求,輸出下面數組中每個數與 10 的餘數

List<Integer> numbers = new ArrayList<>();
        for (int i = 5; i >= 0; i--) {
            numbers.add(i);
        }

用RxJava實現如下:

       Observable.from(numbers)
                .map(new Func1<Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer) {
                        return 10 % integer;
                    }
                })
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        Log.e(MainActivity.class.getSimpleName(), "onCompleted");
                    }
                    @Override
                    public void onError(Throwable e) {
                        Log.e(MainActivity.class.getSimpleName(), "onError---->" + e.getMessage());
                    }
                    @Override
                    public void onNext(Integer integer) {
                        Log.e(MainActivity.class.getSimpleName(), "onNext---- >Remainder is " + integer);
                    }
                });

輸出:

這裏寫圖片描述

可以看到,這裏出錯了,數組中有一項爲0 ,導致了除數爲0,發生了異常,但是程序並沒有崩潰,而是拋出了異常信息。同時onError方法執行了,而onComplete()方法沒有執行。

我們修復一下這個錯誤(這裏假設我們無法修改初始數據,也就是這裏的numbers數組)

Observable.from(numbers)
                .filter(new Func1<Integer, Boolean>() {
                    @Override
                    public Boolean call(Integer integer) {
                        return integer!=0;
                    }
                })
                .map(new Func1<Integer, Integer>() {
                    @Override
                    public Integer call(Integer integer) {
                        return 10 % integer;
                    }
                })
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        Log.e(MainActivity.class.getSimpleName(), "onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e(MainActivity.class.getSimpleName(), "onError---->" + e.getMessage());
                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.e(MainActivity.class.getSimpleName(), "onNext---- >Remainder is " + integer);
                    }
                });

輸出如下:

這裏寫圖片描述

我們使用RxJava的操作符filter 過濾掉了0,這樣就不會有錯誤,最終執行了onCompleted方法。

從上面的例子中,我們得出如下結論:

  1. 在一次完整的事件中,onNext可能會執行0-n次,而onError() 和 onCompleted()中必有一個方法會執行。
  2. 有異常發生,onError就會調用
  3. 訂閱者如果完成了所有事件的處理,onCompleted就會執行,使得我們可以得知整個事件結束了
  4. 操作符不負責處理異常,而是由訂閱者處理。

這裏想一下,按照以往的方式,發生錯誤時,通常是在每個回調中處理錯誤。這不僅導致了重複的代碼,並且意味着每個回調都必須知道如何處理錯誤,你的回調代碼將和調用者緊耦合在一起。

使用RxJava,Observable對象根本不需要知道如何處理錯誤!操作符也不需要處理錯誤狀態-一旦發生錯誤,就會跳過當前和後續的操作符。所有的錯誤處理都交給訂閱者來做。

但是,這種機制也不是完美,有時候我們可能需要對不同的錯誤做出不同的處理,RxJava的機制反而不適合了。

這裏只是對響應式編程思想的簡單瞭解!


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