1. 程式人生 > >RxJava2.x 學習教程(一)基本概念

RxJava2.x 學習教程(一)基本概念

RxJava是什麼、優點

RxJava (本文所有RxJava全都代指RxJava2)在 GitHub 主頁上的自我介紹是:RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM. 
核心就是一個基於事件的非同步的程式庫! 
好處就是解決原生非同步回撥,造成的程式碼冗長、可讀性可維護性差的問題,將其以一種鏈式的平鋪的寫法呈現,更方便維護!(有點類似前端Promise的作用)

implementation 'io.reactivex.rxjava2:rxjava:2.1.12'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

觀察者與被觀察者 
簡單的說, 被觀察者用於傳送事件,觀察者用於接收事件,兩者建立訂閱關係後,就可以實現,被觀察者在需要的時候傳送事件來通知觀察者! 
關於觀察者模式不用過於糾結,只需簡單的理解,被觀察者屬於上游事件來源,用來發送事件,觀察者屬於下游,用於接收事件就ok了! 
RxJava中有兩種觀察者模式:

  • Observable ( 被觀察者 ) / Observer ( 觀察者 )
  • Flowable (被觀察者)/ Subscriber (觀察者)

前者不支援背壓(Backpressure),後者支援! 
背壓是指在非同步場景中,被觀察者傳送事件速度遠快於觀察者的處理速度的情況下,一種告訴上游的被觀察者降低傳送速度的策略。官方對於背壓的解釋

來一個例子

    /*
         RxJava 的三部曲:
         初始化 Observable(被觀察者 事件來源)
         初始化 Observer(觀察者 事件接收)
         建立訂閱關係(將兩者建立聯絡 被觀察者可以通過發射事件通知觀察者)

    */
    private void testRxJava1() {
       Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                //發射事件
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                Log.e("TAG", "emitter on...");
                emitter.onComplete();
                Log.e("TAG", "emitter complete and on...");
                emitter.onNext(4);
            }
        });
       Observer<Integer> observer = new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                //Disposable可以做到切斷的操作,讓Observer觀察者不再接收上游事件
                Log.d("TAG", "subscribe");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d("TAG", "integer = " + integer);
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "onError");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "onComplete");
            }
        };
        observable.subscribe(consumer);//建立訂閱關係
    }
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: subscribe
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: integer = 1
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: integer = 2
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: integer = 3
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: emitter on...
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: onComplete
05-19 11:50:57.050 2321-2321/com.example.rxjava.rxjavademo E/TAG: emitter complete and on...

從上面的結果可以看出,事件發射執行的一些順序,規則!如被觀察者呼叫emitter.onComplete();之後,雖然下面的事件繼續發射,但是觀察者並沒有接收!

ObservableEmitter 事件發射器 它可以通過呼叫emitter的onNext(T value)、onComplete()和onError(Throwable error)分別發出next事件、complete事件和error事件,它有以下幾點需要注意的地方:

  • 官方推薦當呼叫onComplete或者onError,作為結束標誌後,不應再發射事件
  • onComplete或者onError應當只調用一次
  • 其實你違背了上述原則,也沒事,如呼叫onComplete之後,可以繼續發射事件,但是下游觀察者無法接收

Disposable,可以通過呼叫他的dispose()方法,讓下游觀察者無法繼續接收事件!

    //將上面那個例子鏈起來 就是RxJava經典寫法鏈式操作
    private void testRxJava1() {
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                Log.e("TAG", "emitter on...");
                emitter.onComplete();
                Log.e("TAG", "emitter complete and on...");
                emitter.onNext(4);
            }
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d("TAG", "subscribe");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d("TAG", "integer = " + integer);
            }

            @Override
            public void onError(Throwable e) {
                Log.d("TAG", "onError");
            }

            @Override
            public void onComplete() {
                Log.d("TAG", "onComplete");
            }
        });
    }

另外, subscribe()有多個過載的方法:

public final Disposable subscribe() {}
public final Disposable subscribe(Consumer<? super T> onNext) {}
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {} 
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
public final void subscribe(Observer<? super T> observer) {}

帶有一個Consumer引數的subscribe

上面這個例子,可以用java8的箭頭函式,進一步簡化

05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: emmiter 1
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: accept integer = 1
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: emmiter 2
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: accept integer = 2
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: emmiter 3
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: accept integer = 3
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: emmiter 4
05-19 15:25:11.290 7170-7170/com.example.rxjava.rxjavademo E/TAG: emmiter 5

帶有兩個引數的subscribe() :

   Observable.just(1, "2")
             .cast(Integer.class)//將被觀察者傳送的事件資料型別強轉為Integer
             .subscribe(new Consumer<Integer>() {//只處理onNext
                 @Override
                 public void accept(Integer integer) throws Exception {
                     Log.e("TAG", "" + integer);
                 }
             }, new Consumer<Throwable>() {//捕獲異常
                 @Override
                 public void accept(Throwable throwable) throws Exception {
                     Log.e("TAG", throwable.getMessage());
                 }
             });

當然它也可以用java8的箭頭函式改寫:

    Observable.just(1, "2")
              .cast(Integer.class)
              .subscribe(integer -> Log.e("TAG", "" + integer), 
                         throwable -> Log.e("TAG", throwable.getMessage()));

執行結果

05-22 15:15:54.405 6034-6034/com.example.rxjava.rxjavademo E/TAG: 1
05-22 15:15:54.405 6034-6034/com.example.rxjava.rxjavademo E/TAG: java.lang.String cannot be cast to java.lang.Integer

這裡只是對基本概念的介紹,對RxJava有一個基本瞭解,後續會進行詳細的用法解讀! 

                                                                  
                                                                           全棧開發者微信公眾號 

相關推薦

RxJava2.x 學習教程基本概念

RxJava是什麼、優點 RxJava (本文所有RxJava全都代指RxJava2)在 GitHub 主頁上的自我介紹是:RxJava – Reactive Extensions for the JVM – a library for composing asynch

RxJava2.x 學習教程常用操作符

錯誤處理類  Retry 當原始Observable在遇到錯誤時進行重試,目的是希望本次訂閱不以失敗事件結束! Observable.just(1, "2") .cast(Integer.class)//將被觀察者傳送的事件資料型別強轉為Intege

RabbitMQ學習筆記-----------------基本概念知識

                         

Unity學習筆記——基本概念之場景Scene

場景,顧名思義就是我們在遊戲中所看到的物品、建築、人物、背景、聲音、特效等,基本上和我們玩遊戲時所看到的遊戲“場景”是同一個概念。 Unity 3D中,“場景”是一個檢視,我們通過“場景”這個檢視,來編輯、佈置遊戲中玩家所能見到的影象和聲音。 安裝完並執行Unity 3D,

Maven學習基本配置

http pat pos tps nco path 9.png color pac 安裝maven還幾次沒成功,不過最後還是查資料成功了,所以記錄一下。 1.安裝JDK,比較簡單,就不說明了。 2.配置java的環境變量 JAVA_HOME (最開始因為java配置成C:\

SpringBoot 2.X 學習筆記Spring Boot HelloWorld

pre urn art release ret XML tap tro 簡化 Spring Boot HelloWorld 實現一個最簡單的功能:瀏覽器發送hello請求,服務器接受請求並處理,響應Hello World字符串; 1、創建一個maven工程;(jar) 2、

Cocos2d-x學習筆記HelloCpp的來龍去脈

【1】首先分析HelloCpp專案的檔案結構,分為Classes、win32、外部檔案依賴三個資料夾,其中外部依賴資料夾暫且不用理會。 Classes主要包含像導演、場景、佈景、攝像機、精靈、App相關類的申明和定義; Win32主要是應用程式框架的WinMain函式入口(包

webService學習基本概念和環境搭建

1、webService概念理解: WebService是一種跨程式語言和跨作業系統平臺的遠端呼叫技術。 所謂遠端呼叫,就是一臺計算機a上 的一個程式可以呼叫到另外一臺計算機b上的一個物件的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬呼叫的轉賬方法的程式碼其實是跑在銀

python面向物件學習基本概念

目錄 1. 面向物件基本概念 1.1 過程和函式 1.2 面相過程 和 面相物件 基本概念 2. 類和物件的概念 1.1 類 1.3 物件 3. 類和物件的關係 4. 類的設計 大駝峰命名法 4.1 類名的確

增強學習 ----- 基本概念

機器學習演算法大致可以分為三種:     1. 監督學習(如迴歸,分類)     2. 非監督學習(如聚類,降維)     3. 增強學習 什麼是增強學習呢? 增強學習(reinforc

軟體測試學習教程-學習路線圖

寫這些,一些是個人總結與學習,一些是彙總他人經驗與智慧,他山之石可以攻玉,無論如何,知識共享才是最終目的,希望可以為想入軟體測試行業的小白明確學習的方向,也可以幫助工作多年的中高階工程師能查漏補缺,更歡迎能對文章體現的不當之處予以糾正,對不足之處加以補充,為後來者開闢道路,指

pygame學習教程pygame介紹引自官網

網上有很多pygame的教程,我寫這個系列是因為我在學習的過程中響起當年Win32程式設計,自己編寫Form,Message,事件響應。雖然現在已經有很多方法可以幫我們實現這些,如果自己寫一遍會體會很深。 第一篇介紹。 https://www.pygame.org/docs/tut/Pyga

Scala快速學習教程

    在學習spark時使用到了scala語言進行程式設計,特編寫此部落格,已儘量精簡的方式對scala語言進行總結學習(在至少會一門程式語言的基礎上看此篇部落格會比較容易)。Scala運行於Java平臺(JVM,Java 虛擬機器)上,併兼容現有的Java程式,Scala

hibernate簡單入門教程---------基本配置

應用級別所以很粗淺 首先介紹一下hibernate框架: 1.優秀的持久化(通俗講把記憶體上的短時間執行資訊儲存在持久化硬碟上)框架。 2.作用於持久層,因為沒什麼侵入性,所以同樣適用於其他層面上的儲存 3.高度整合jdbc,簡化了很多jdbc的操作。比如查詢,比如儲存 4.二級快取。快取一部分所查

Selenium Python 學習教程

安裝python 開啟 Python官網,找到“Download”, 在其下拉選單中選擇自己的平臺(Windows/Mac),一般的Linux平臺已經自帶的Python,所以不需要安裝,通過開啟“終端” ,輸入“python”命令來驗證。 如果你是第一次接觸Python,一定會迷惑Pyt

JVM學習筆記------基本結構

從Java平臺的邏輯結構上來看,我們可以從下圖來了解JVM: 從上圖能清晰看到Java平臺包含的各個邏輯模組,也能瞭解到JDK與JRE的區別 對於JVM自身的物理結構,我們可以從下圖鳥瞰一下: 對於JVM的學習,在我看來這麼幾個部分最重要: Java程式碼編譯和執行的整個

小程式學習記錄——基本樣式介紹

這些天到處跑面試,結果屢屢碰壁。原因除了技術問題、生活上的問題外,遇到的最大的問題就是沒有 小程式 開發經驗了。於是我搜集了一些小程式的資料,結合慕課網、微信開放平臺相關內容進行學習。這個系列將會從我實際學習中出發,去講述我從學習小程式過程中獲得的內容。  詳細安裝、申

arcgis for js 3.x 學習記錄

一:侃 4.x主要更新的是對3維的操作吧,我們專案目前沒用到3維地圖,然後客戶那面裝的也都是arcgis 10.1?,所以覺得還是用3.x比較好,目前我們專案用的是arcgis for js  3.19 arcgis for js 3 開發者資料地址:https://dev

HTML學習筆記———基本結構

一.html文件結構 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">  <!--文件型別宣告--> <html>

Kubernetes | 學習教程 Kubernetes 1.9.0 離線安裝教程

為了讓產品在迎來業務量爆發式增長前完成應對措施,在瀏覽無數的資料後,決定將服務逐漸進行容器化,最終能達到容器叢集的效果。而容器叢集的解決方案中,kubernetes(簡稱k8s)看起來是個可行的方案。我目前的理解是,k8s就是docker容器叢集的一個管理系統,有很多實用功能