RxJava 入門詳解

一、ReactiveX簡介

在學習RxJava前首先需要了解ReactiveX,因爲RxJava是ReactiveX的一種Java的實現形式。

ReactiveX的官網地址爲:ReactiveX的官網
ReactiveX官網對於自身的介紹是:

An API for asynchronous programming with observable streams
實質上我們可以對其解讀爲三部分:

ReactiveX的解讀

  • ①An API: 首先它是個編程接口,不同語言提供不同實現。例如Java中的RxJava。
  • ②For asynchronous programming: 在異步編程設計中使用。例如開啓子線程處理耗時的網絡請求。
  • ③With observable streams: 基於可觀察的事件流。例如觀察者模式中觀察者對被觀察者的監聽。
    而ReactiveX結合瞭如下三部分內容:
  1. 觀察者模式,即定義對象間一種一對多的依賴關係,當一個對象改變狀態時,則所有依賴它的對象都會被改變。
  2. Iterator模式,即迭代流式編程模式。
  3. 函數式編程模式,即提供一系列函數樣式的方法供快速開發。

二、RxJava的使用

1、RxJava的優勢

**在Android的SDK中,給開發者提供的用於異步操作的原生內容有AsyncTask和Handler。**對於簡單的異步請求來說,使用Android原生的AsyncTask和Handler即可滿足需求,但是對於複雜的業務邏輯而言,依然使用AsyncTask和Handler會導致代碼結構混亂,代碼的可讀性非常差。
但是RxJava的異步操作是基於觀察者模式實現的,在越來越複雜的業務邏輯中,RxJava依舊可以保持簡潔。

2、RxJava的配置

首先,在Android Studio中配置Module的build.gradle,在這裏我們使用的版本是1.2版本,並且導入RxAndroid,輔助RxJava完成線程調度:

	implementation "io.reactivex:rxjava:1.2.0"
	implementation "io.reactivex:rxandroid:1.2.0"

然後,RxJava基於觀察者設計模式,其中的關鍵性三個步驟如下:

(1)Observable被觀察者
Observable被觀察者創建的代碼如下:

	Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
	    @Override
	    public void call(Subscriber<? super String> subscriber) {
	        subscriber.onNext("Alex");
	        subscriber.onCompleted();
	    }
	});

在這裏,要強調的是Observable被觀察者是類類型,其中有諸多方法,我們關注其構造函數與創建Observable對象的方法,查看如下圖對應的視圖結構:

圖2.2.1 Observable被觀察者對象的視圖結構

查看源碼:

	protected Observable(OnSubscribe<T> f) {
	   this.onSubscribe = f;
	}
	
	public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
	
	}
	public static <T> Observable<T> create(OnSubscribe<T> f) {
	   return new Observable<T>(RxJavaHooks.onCreate(f));
	}
	
	public static <S, T> Observable<T> create(SyncOnSubscribe<S, T> syncOnSubscribe) {
	   return create((OnSubscribe<T>)syncOnSubscribe);
	}
	
	public static <S, T> Observable<T> create(AsyncOnSubscribe<S, T> asyncOnSubscribe) {
	   return create((OnSubscribe<T>)asyncOnSubscribe);
	}

通過源碼分析,可知Observable提供了create()方法來獲取Observable實例對象。
此外,除了基本的創建的方法,Observable還提供了便捷的創建Observable序列的兩種方式,代碼如下:

  • 第一種,會將參數逐個發送
    Observable observable1 = Observable.just(“Alex”,“Payne”);
  • 第二種,會將數組元素逐個轉換完畢後逐個發送
    String[] observableArr = {“Alex”, “Payne”};
    Observable observable2 = Observable.from(observableArr);

其中Observable.just()方法會調用from()方法,詳情可查看源碼。

(2)Observer觀察者
Observer觀察者創建的代碼如下:

	Observer<String> observer = new Observer<String>() {
	
	    @Override
	    public void onCompleted() {
	        Log.e(TAG, "onCompleted");
	    }
	
	    @Override
	    public void onError(Throwable e) {
	        Log.e(TAG, "onError,Error Info is:" + e.getMessage());
	    }
	
	    @Override
	    public void onNext(String s) {
	        Log.e(TAG, s);
	    }
	};

Observer是接口,其中包含的方法有onCompleted()、onNext()、onError()。查看如下圖所示Observer的視圖結構:

圖2.2.2 Observer觀察者對象的視圖結構

那麼在RxJava中,Observer有其接口實現類對象Subscriber,它們的使用onNext、onCompleted、onError方法是一樣的,但是Subscriber對於Observer接口進行了拓展,在 RxJava 的 subscribe 過程中,Observer 也總是會先被轉換成一個 Subscriber 再使用,代碼如下:

	Subscriber<String> subscriber = new Subscriber<String>() {
	    @Override
	    public void onStart() {
	        Log.e(TAG, "onStart");
	    }
	
	    @Override
	    public void onCompleted() {
	        Log.e(TAG, "onCompleted");
	    }
	
	    @Override
	    public void onError(Throwable e) {
	        Log.e(TAG, "onError,Error Info is:" + e.getMessage());
	
	    }
	
	    @Override
	    public void onNext(String s) {
	        Log.e(TAG, s);
	    }
	};

其中,onStart()方法會在事件未發送前被調用,可以用於訂閱關係建立前的準備工作,例如將數據清空或者重置,在Subscriber中默認是空實現,我們可以在該方法中調用自己的業務邏輯代碼。在如下的視圖結構中我們可以看到Subscriber的拓展內容,重點是add()、unsubscribe()方法以及名爲subscription的Subscription隊列。

圖2.2.3 Subscriber對象視圖結構
(3)Subscribe訂閱關係
Observable與observer形成訂閱關係代碼如下:

        observable.subscribe(observer);
        //或者
        observable.subscribe(subscriber);

那麼我們以observable.subscribe(observer)爲例在這裏繼續查看源碼,查看subscribe()方法到底做了什麼:

圖2.3.1 Observable調用Subscribe將Observer轉換爲Subscriber對象

Observer轉換爲Subscriber對象在這裏得到印證。

在之後的內容中統一以Subscriber作爲訂閱觀察者對象
繼續深入,我們可以看到訂閱關係中的關鍵步驟(僅核心代碼):

    subscriber.onStart();

    RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber);

    return RxJavaHooks.onObservableReturn(subscriber);

在這裏RxJavaHooks.onObservableStart(observable, observable.onSubscribe).call(subscriber)等價於OnSubscribe.call(subscriber)

可以看到,subscriber() 做了3件事:
調用 Subscriber.onStart() 。該方法用於在訂閱關係建立之前的準備。
調用 Observable 中的 OnSubscribe.call(Subscriber) 。OnSubscribe是Observable的內部接口,而事件發送的邏輯在這裏開始運行。從這也可以看出,在 RxJava 中當 subscribe() 方法執行的時候訂閱關係確立,Observable 開始發送事件。
將傳入的 Subscriber 作爲 Subscription 返回。這是爲了方便後續調用unsubscribe()。

三、RxJava的不完整回調

1、不完整回調的代碼示例

	Observable<String> observable = Observable.just("Alex", "Payne");
	Action1<String> onNextAction = new Action1<String>() {
	    @Override
	    public void call(String s) {
	        Log.e(TAG, s);
	    }
	};
	Action1<Throwable> onErrorAction = new Action1<Throwable>() {
	    @Override
	    public void call(Throwable throwable) {
	        Log.e(TAG, "onError,Error Info is:" + throwable.getMessage());
	    }
	};
	Action0 onCompletedAction = new Action0() {
	    @Override
	    public void call() {
	        Log.e(TAG, "onCompleted");
	    }
	};
	
	// 根據onNextAction 來定義 onNext()
	observable.subscribe(onNextAction);
	// 根據onNextAction 來定義 onNext()、根據onErrorAction 來定義 onError()
	observable.subscribe(onNextAction, onErrorAction);
	// 根據onNextAction 來定義 onNext()、根據onErrorAction 來定義 onError()、onCompletedAction 來定義 onCompleted()
	observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

2、不完整回調的原理分析

在這裏我們可以看到:

  • Action0無參數泛型無返回值類型,而Subscriber中的onCompleted()方法也沒有參數泛型
  • Action1有1個參數泛型無返回值類型 ,onNextAction設置的參數泛型爲String,而Subscriber中的onNext()方法參數泛型也是String(和本文中觀察者對象中的OnNext方法對比)
  • Action1有1個參數泛型無返回值類型,onErrorAction設置的參數泛型爲Throwable,而Subscriber中的onError()方法參數泛型也是Throwable

那麼,我們來查看observable.subscribe(onNextAction)的源碼,在這裏, Action1可以被當成一個包裝對象,將onNext()方法進行包裝作爲不完整的回調傳入到observable.subscribe()中。

圖3.2.1 傳入的onNextAction最終被包裝成ActionSubscriber

我們來看看Action1有何玄機,Action1的源碼如下圖所示:

圖3.2.2 Action1接口源碼

實質上,這種根據參數泛型的個數且無返回值類型的包裝在RxJava中有多種如下圖所示的體現,例如Action0的參數個數爲0,Action1的參數個數爲1以此類推:
圖3.2.3 根據參數泛型的個數且無返回值類型的包裝

四、RxJava的線程切換

1、Scheduler線程調度器

如果不指定線程,默認是在調用subscribe方法的線程上進行回調,那麼如果子線程中調用subscibe方法,而想在主線程中進行UI更新,則會拋出異常。當然了RxJava已經幫我們考慮到了這一點,所以提供了Scheduler線程調度器幫助我們進行線程之間的切換。
實質上,Scheduler線程調度器和RxJava的操作符有緊密關聯,我將在下一篇文章中進行詳細介紹。

RxJava內置瞭如下所示幾個的線程調度器:

  • Schedulers.immediate():在當前線程中執行
  • Schedulers.newThread():啓動新線程,在新線程中進行操作
  • Schedulers.io(): I/O 操作(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler。行爲模式和 newThread() 差不多,區別在於 io() 的內部實現是是用一個無數量上限的線程池,可以重用空閒的線程,因此多數情況下 io() 比 newThread() 更有效率。不要把計算工作放在 io() 中,可以避免創建不必要的線程。
  • Schedulers.computation():計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操作限制性能的操作,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操作放在 computation() 中,否則 I/O 操作的等待時間會浪費 CPU。
  • Schedulers.trampoline():會將任務按添加順序依次放入當前線程中等待執行。線程一次只執行一個任務,其餘任務排隊等待,一個任務都執行完成後再開始下一個任務的執行。

此外RxJava還提供了用於測試的調度器Schedulers.test() 及 可自定義Scheduler—-Schedulers.form() 。
RxAndroid並且其爲我們提供了AndroidSchedulers.mainThread()進行主線程的回調

2、線程控制

調用Observable對象的subscribeOn()、observeOn()方法即可完成線程控制。

  • subscribeOn(): 指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程。
  • observeOn(): 指定 Subscriber 所運行在的線程。或者叫做事件消費的線程。
	 Observable.just("Alex", "Payne")
	.subscribeOn(Schedulers.io())//指定 subscribe() 所發生的線程
	.unsubscribeOn(Schedulers.io())//事件發送完畢後,及時取消發送
	.observeOn(AndroidSchedulers.mainThread())//指定 Subscriber 所運行在的線程
	.subscribe(new Action1<String>() {
	    @Override
	      public void call(String s) {
	          Log.e(TAG, s);
	     }
	 });

五、總結

本文主要介紹了RxJava的由來、使用步驟、部分內容的原理解析。在下篇文章中我會詳細介紹RxJava的操作符。希望本文對你在學習RxJava的路上有所啓發。

在這裏插入圖片描述

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