1. 程式人生 > >Android RxJava實際應用案例講解:使用RxJava的最佳開發場景

Android RxJava實際應用案例講解:使用RxJava的最佳開發場景

前言

  • Rxjava由於其基於事件流的鏈式呼叫、邏輯簡潔 & 使用簡單的特點,深受各大 Android開發者的歡迎。

Github截圖

  • 今天,我將為大家帶來 Rxjava的的基本使用 & 實際應用案例教學,即常見開發應用場景實現 ,並結合常用相關框架如Retrofit等,希望大家會喜歡。
    1. 本系列文章主要基於 Rxjava 2.0
    2. 接下來的時間,我將持續推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、應用場景、背壓等等 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記!!

示意圖

目錄

示意圖

1. 簡介

RxJava的簡介如下

示意圖

2. 基本使用

  • Rxjava的使用方式有兩種:
    方式1:分步驟實現
    示意圖
    方式2:基於事件流的鏈式呼叫

3. 實際開發應用場景

  • RxJava的實際開發應用場景 與 其對應的操作符息息相關
  • 常見的RxJava實際開發應用場景有如下:

示意圖

  • 下面,我將對每個實際開發應用場景進行例項講解教學
    下面例項皆結合常用框架如RetrofitRxBindingRxBus

3.1 網路請求輪詢(無條件)

3.2 網路請求輪詢(有條件)

3.3 網路請求出錯重連

  • 需求場景
    示意圖

  • 功能需求說明

示意圖

  • 功能邏輯

示意圖

3.4 網路請求巢狀回撥

  • 背景
    需要進行巢狀網路請求:即在第1個網路請求成功後,繼續再進行一次網路請求

    如 先進行 使用者註冊 的網路請求, 待註冊成功後回再繼續傳送 使用者登入 的網路請求

  • 衝突
    巢狀實現網路請求較為複雜,即巢狀呼叫函式

    下面展示的是結合 RetrofitRxJava的基本用法,即未用操作符前

// 傳送註冊網路請求的函式方法
    private void register() {
        api.register(new RegisterRequest())
                .subscribeOn(Schedulers.io())               //在IO執行緒進行網路請求
.observeOn(AndroidSchedulers.mainThread()) //回到主執行緒去處理請求結果 .subscribe(new Consumer<RegisterResponse>() { @Override public void accept(RegisterResponse registerResponse) throws Exception { Toast.makeText(MainActivity.this, "註冊成功", Toast.LENGTH_SHORT).show(); login(); //註冊成功, 呼叫登入的方法 } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { Toast.makeText(MainActivity.this, "註冊失敗", Toast.LENGTH_SHORT).show(); } }); } // 傳送登入網路請求的函式方法 private void login() { api.login(new LoginRequest()) .subscribeOn(Schedulers.io()) //在IO執行緒進行網路請求 .observeOn(AndroidSchedulers.mainThread()) //回到主執行緒去處理請求結果 .subscribe(new Consumer<LoginResponse>() { @Override public void accept(LoginResponse loginResponse) throws Exception { Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show(); } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { Toast.makeText(MainActivity.this, "登入失敗", Toast.LENGTH_SHORT).show(); } }); }

3.5 從磁碟 / 記憶體快取中 獲取快取資料

3.6 合併資料來源

  • 需求場景

示意圖

  • 功能說明
    即,同時向2個數據源獲取資料 -> 合併資料 -> 統一展示到客戶端

3.7 聯合判斷

  • 需求場景
    需要同時對多個事件進行聯合判斷

    如,填寫表單時,需要表單裡所有資訊(姓名、年齡、職業等)都被填寫後,才允許點選 “提交” 按鈕

  • 功能說明
    此處採用 填寫表單 作為聯合判斷功能展示,即,表單裡所有資訊(姓名、年齡、職業等)都被填寫後,才允許點選 “提交” 按鈕

3.8 執行緒控制(切換 / 排程 )

3.9 功能防抖

  • 需求場景
    示意圖

  • 功能說明

示意圖

3.10 聯想搜尋優化

  • 需求場景
    示意圖

  • 功能說明

示意圖

3.11 控制被觀察者傳送事件 & 觀察者接收事件速度:背壓

a. 背景

  • 觀察者 & 被觀察者 之間存在2種訂閱關係:同步 & 非同步。具體如下:

示意圖

  • 對於非同步訂閱關係,存在 被觀察者傳送事件速度 與觀察者接收事件速度 不匹配的情況
    1. 傳送 & 接收事件速度 = 單位時間內 傳送&接收事件的數量
    2. 大多數情況,主要是 被觀察者傳送事件速度 > 觀察者接收事件速度

b. 衝突
  • 被觀察者 傳送事件速度太快,而觀察者 來不及接收所有事件,從而導致觀察者無法及時響應 / 處理所有傳送過來事件的問題,最終導致快取區溢位、事件丟失 & OOM
  • 如,點選按鈕事件:連續過快的點選按鈕10次,則只會造成點選2次的效果;
  • 解釋:因為點選速度太快了,所以按鈕來不及響應
  • 下面再舉個例子:
    • 被觀察者的傳送事件速度 = 10ms / 個
    • 觀察者的接收事件速度 = 5s / 個

    即出現傳送 & 接收事件嚴重不匹配的問題

     Observable.create(new ObservableOnSubscribe<Integer>() {
                // 1. 建立被觀察者 & 生產事件
                @Override
                public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
    
                    for (int i = 0; ; i++) {
                        Log.d(TAG, "傳送了事件"+ i );
                        Thread.sleep(10);
                        // 傳送事件速度:10ms / 個 
                        emitter.onNext(i);
    
                    }
    
                }
            }).subscribeOn(Schedulers.io()) // 設定被觀察者在io執行緒中進行
                    .observeOn(AndroidSchedulers.mainThread()) // 設定觀察者在主執行緒中進行
                 .subscribe(new Observer<Integer>() {
                // 2. 通過通過訂閱(subscribe)連線觀察者和被觀察者
    
                @Override
                public void onSubscribe(Disposable d) {
                    Log.d(TAG, "開始採用subscribe連線");
                }
    
                @Override
                public void onNext(Integer value) {
    
                    try {
                        // 接收事件速度:5s / 個 
                        Thread.sleep(5000);
                        Log.d(TAG, "接收到了事件"+ value  );
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
    
                @Override
                public void onError(Throwable e) {
                    Log.d(TAG, "對Error事件作出響應");
                }
    
                @Override
                public void onComplete() {
                    Log.d(TAG, "對Complete事件作出響應");
                }
    
            });
    • 結果
      由於被觀察者傳送事件速度 > 觀察者接收事件速度,所以出現流速不匹配問題,從而導致OOM
      示意圖

    c. 解決方案
    採用 背壓策略

    至此,關於RxJava常見的實際開發應用場景講解完畢。

    4. 總結

    • 本文主要對 RxJava2 中常用的實際開發應用場景講解進行了詳細介紹,下面用1張圖進行總結

    示意圖

    • 接下來,我將持續推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、應用場景、背壓等等 ,有興趣可以繼續關注Carson_Ho的安卓開發筆記!!

    示意圖

    幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!