Carson帶你學Android:這是一篇清晰易懂的Rxjava入門教程


前言

Rxjava由于其基于事件流的鏈式調用、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。本文主要:

  1. 面向 剛接觸Rxjava的初學者
  2. 提供了一份 清晰、簡潔、易懂的Rxjava入門教程,涵蓋 基本介紹、原理 & 具體使用等
  3. 解決的是初學者不理解Rxjava原理 & 不懂得如何使用的問題

Carson帶你學RxJava系列文章,包括 原理、操作符、應用場景、背壓等等,請關注看文章:Android:這是一份全面 & 詳細的RxJava學習指南


目錄

示意圖

1. 定義

  • RxJavaGitHub 的介紹:
RxJava:a library for composing asynchronous and event-based programs using observable sequences for the Java VM
// 翻譯:RxJava 是一個在 Java VM 上使用可觀測的序列來組成異步的、基于事件的程序的庫
  • 總結:RxJava 是一個 基于事件流、實現異步操作的庫

2. 作用

實現異步操作

類似于 Android中的 AsyncTaskHandler作用


3. 特點

由于 RxJava的使用方式是:基于事件流的鏈式調用,所以使得 RxJava

  • 邏輯簡潔
  • 實現優雅
  • 使用簡單

更重要的是,隨著程序邏輯的復雜性提高,它依然能夠保持簡潔 & 優雅


4. 原理

4.1 生活例子引入

  • 我用一個生活例子引入 & 講解 Rxjava原理: 顧客到飯店吃飯
示意圖
流程圖

4.2 Rxjava原理介紹

  • Rxjava原理 基于 一種擴展的觀察者模式

  • Rxjava的擴展觀察者模式中有4個角色:

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

請結合上述 顧客到飯店吃飯 的生活例子理解:

示意圖

流程圖

RxJava原理可總結為:被觀察者 (Observable) 通過 訂閱(Subscribe) 按順序發送事件 給觀察者 (Observer), 觀察者(Observer) 按順序接收事件 & 作出對應的響應動作。具體如下圖:

示意圖

至此,RxJava原理講解完畢。


5. 基本使用

  • 本文只關注 RxJava的基本使用,更深入的RxJava使用請繼續關注Carson_Ho的RxJava系列
  • Rxjava的使用方式有兩種:
    1. 分步驟實現:該方法主要為了深入說明Rxjava的原理 & 使用,主要用于演示說明
    2. 基于事件流的鏈式調用:主要用于實際使用

5.1 方式1:分步驟實現

5.1.1 使用步驟
示意圖
5.1.2 步驟詳解
步驟1:創建被觀察者 (Observable )& 生產事件
  • 即 顧客入飯店 - 坐下餐桌 - 點菜
  • 具體實現
        // 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);
  // 將會依次調用:
  // onNext("A");
  // onNext("B");
  // onNext("C");
  // onCompleted();

步驟2:創建觀察者 (Observer )并 定義響應事件的行為
  • 即 開廚房 - 確定對應菜式
  • 發生的事件類型包括:Next事件、Complete事件 & Error事件。具體如下:
示意圖
  • 具體實現

<--方式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<Integer> 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);
            }

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

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


<--特別注意:2種方法的區別,即Subscriber 抽象類與Observer 接口的區別 -->
// 相同點:二者基本使用方式完全一致(實質上,在RxJava的 subscribe 過程中,Observer總是會先被轉換成Subscriber再使用)
// 不同點:Subscriber抽象類對 Observer 接口進行了擴展,新增了兩個方法:
    // 1. onStart():在還未響應事件前調用,用于做一些初始化工作
    // 2. unsubscribe():用于取消訂閱。在該方法被調用后,觀察者將不再接收 & 響應事件
    // 調用該方法前,先使用 isUnsubscribed() 判斷狀態,確定被觀察者Observable是否還持有觀察者Subscriber的引用,如果引用不能及時釋放,就會出現內存泄露
步驟3:通過訂閱(Subscribe)連接觀察者和被觀察者
  • 即 顧客找到服務員 - 點菜 - 服務員下單到廚房 - 廚房烹調
  • 具體實現
observable.subscribe(observer);
 // 或者 observable.subscribe(subscriber);
  • 擴展說明
<-- Observable.subscribe(Subscriber) 的內部實現 -->

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

5.2 方式2:優雅的實現方法 - 基于事件流的鏈式調用

  • 上述的實現方式是為了說明Rxjava的原理 & 使用
  • 在實際應用中,會將上述步驟&代碼連在一起,從而更加簡潔、更加優雅,即所謂的 RxJava基于事件流的鏈式調用
// 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事件作出響應");
            }

        });
    }
}

注:整體方法調用順序:觀察者.onSubscribe()> 被觀察者.subscribe()> 觀察者.onNext()>觀察者.onComplete() 

這種 基于事件流的鏈式調用,使得RxJava

  • 邏輯簡潔
  • 實現優雅
  • 使用簡單

更重要的是,隨著程序邏輯的復雜性提高,它依然能夠保持簡潔 & 優雅。所以,一般建議使用這種基于事件流的鏈式調用方式實現RxJava

特別注意

RxJava 2.x 提供了多個函數式接口 ,用于實現簡便式的觀察者模式。具體如下:

示意圖

Consumer為例:實現簡便式的觀察者模式

Observable.just("hello").subscribe(new Consumer<String>() {
            // 每次接收到Observable的事件都會調用Consumer.accept()
            @Override
            public void accept(String s) throws Exception {
                System.out.println(s);
            }
        });

6. 實例說明

我將用一個實際工程實例來演示 Rxjava的使用

6.1 方式1:分步驟實現

步驟1:加入依賴

    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>() {
            // 通過復寫對應方法來 響應 被觀察者
            @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事件作出響應");
            }
        };

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

6.2 方式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事件作出響應");
            }

        });
    }
}

喜歡的麻煩點個star


7. 額外說明

7.1 被觀察者 Observable的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) {}
    // 表示觀察者對被觀察者發送的任何事件都作出響應

7.2 可采用 Disposable.dispose() 切斷觀察者 與 被觀察者 之間的連接

  • 即觀察者 無法繼續 接收 被觀察者的事件,但被觀察者還是可以繼續發送事件
  • 具體使用

// 主要在觀察者 Observer中 實現
        Observer<Integer> observer = new Observer<Integer>() {
            // 1. 定義Disposable類變量
            private Disposable mDisposable;

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "開始采用subscribe連接");
                // 2. 對Disposable類變量賦值
                mDisposable = d;
            }

            @Override
            public void onNext(Integer value) {
                Log.d(TAG, "對Next事件"+ value +"作出響應"  );
                if (value == 2) {
                    // 設置在接收到第二個事件后切斷觀察者和被觀察者的連接
                    mDisposable.dispose();
                    Log.d(TAG, "已經切斷了連接:" + mDisposable.isDisposed());
                }
            }

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

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

8. 總結

  • 本文主要對 Rxjava 的入門知識進行講解,包括基本介紹、原理 & 具體使用等
  • Carson帶你學RxJava系列文章:

入門
Carson帶你學Android:這是一篇清晰易懂的Rxjava入門教程
Carson帶你學Android:面向初學者的RxJava使用指南
Carson帶你學Android:RxJava2.0到底更新了什么?
原理
Carson帶你學Android:圖文解析RxJava原理
Carson帶你學Android:手把手帶你源碼分析RxJava
使用教程:操作符
Carson帶你學Android:RxJava操作符教程
Carson帶你學Android:RxJava創建操作符
Carson帶你學Android:RxJava功能性操作符
Carson帶你學Android:RxJava過濾操作符
Carson帶你學Android:RxJava組合/合并操作符
Carson帶你學Android:RxJava變換操作符
Carson帶你學Android:RxJava條件/布爾操作符
實戰
Carson帶你學Android:什么時候應該使用Rxjava?(開發場景匯總)
Carson帶你學Android:RxJava線程控制(含實例講解)
Carson帶你學Android:圖文詳解RxJava背壓策略
Carson帶你學Android:RxJava、Retrofit聯合使用匯總(含實例教程)
Carson帶你學Android:優雅實現網絡請求嵌套回調
Carson帶你學Android:網絡請求輪詢(有條件)
Carson帶你學Android:網絡請求輪詢(無條件)
Carson帶你學Android:網絡請求出錯重連(結合Retrofit)
Carson帶你學Android:合并數據源
Carson帶你學Android:聯想搜索優化
Carson帶你學Android:功能防抖
Carson帶你學Android:從磁盤/內存緩存中獲取緩存數據
Carson帶你學Android:聯合判斷


歡迎關注Carson_Ho的簡書

不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度


請點贊!因為你的鼓勵是我寫作的最大動力!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容