##寫在前面
前篇文章簡單介紹了一下RxJava的概念與基本使用,本來準備繼續說一下RxJava的進階使用,包括一些複雜操作符的使用與執行緒控制的相關內容。然後想了想,不能這樣急躁地去學如何使用,應該先稍微明白它的一些過程,後面學習起來思路更加清晰,這也是我之前學習RxJava的一個誤區所在。
所以今天這篇文章,打算先認識一下基本的常見的兩種操作符及其使用,然後採用圖文的模式詳細介紹一下RxJava的基礎原始碼,主要包括create()與subscribe()這兩個方法到底做了什麼事情。
有了這兩個基礎後,後期學大量複雜且重要的操作符及其原理就有了基本的認知,至少學到複雜的地方不慌。而採用圖文模式講解原始碼看起來也不煩躁,輕輕鬆鬆得去學習。
下面是本文的目錄:
- 寫在前面
- 初識操作符
- Observable.just()
- Observable.from()
- 基礎原始碼
- create()
- subscribe()
- 結語
- 參考資料
- 專案原始碼
##初識操作符
所謂操作符(Operators),簡單來說就是一種指令,表示需要執行什麼樣的操作。Rx中的每種程式語言實現都實現了一組操作符的集合。RxJava也不例外。
RxJava中有大量的操作符,比如建立操作符、變換操作符、過濾操作符等等,這些操作符要全部講解完幾乎是不可能也沒必要的事情。所以我們只介紹常見的、有用的、重要的操作符。其他的如果用到直接到文件查詢就行了。
下面就針對前篇文章的建立(create)來說明一下另外兩種常見的建立操作符。先來回顧一下create()操作符,比較簡單,這裡就不解釋了:
//建立Observable
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("World");
subscriber.onCompleted();
}
}).subscribe(new Observer<String>() {
@Override
public void onNext(String s) {
Log.i("onNext ---> ", s);
}
@Override
public void onCompleted() {
Log.i("onCompleted ---> ", "完成");
}
@Override
public void onError(Throwable e) {
}
});
複製程式碼
###Observable.just()
首先給出定義:
Just操作符是建立一個將引數依次傳送出來的Observable
具體一點來說就是, just() 中會接收1~9個引數,它會返回一個按照傳入引數的順序依次傳送這些引數的Observable。
這樣說可能還是不夠清晰,所以畫個圖來看:
從圖中可以看出,其實就是依次傳送單個資料,它的具體寫法是這樣的,非常簡單:
Observable.just("Hello","world");
//其實就相當於依次呼叫:
//subscriber.onNext("Hello");
//subscriber.onNext("World");
複製程式碼
但是這裡要注意一點,如果你傳遞null給just,它會返回一個傳送null值的Observable,而不是返回一個空Observable(完全不傳送任何資料的Observable)。後面會講到,如果需要空Observable應該使用 Empty 操作符。
現在來看完整的程式碼,程式碼本身很簡單,注意看Log日誌:
//建立Observable
Observable.just("Hello", "World", null)
.subscribe(new Observer<String>() {
@Override
public void onNext(String s) {
if (s == null) {
Log.i("onNext ---> ", "null");
}else {
Log.i("onNext ---> ", s);
}
}
@Override
public void onCompleted() {
Log.i("onCompleted ---> ", "完成");
}
@Override
public void onError(Throwable e) {
Log.i("onError ---> ", "出錯 --->" + e.toString());
}
});
複製程式碼
這裡因為我們要列印字串,所以不能為null,我就處理了一下,可以看到當傳送 null 的時候,s確實等於null。
###Observable.from()
儘管與just一樣是建立操作符,但是from操作符稍微強大點。因為from操作符的作用是:
將傳入的陣列或 Iterable 拆分成具體物件後,依次傳送出來。
注意,這裡不再是傳送單個物件,而是直接傳送一組物件。為了與just對比,也來畫個圖描述一下:
它的具體寫法是這樣的,也非常簡單:
String[] str = new String[]{"Hello", "World"};
//建立Observable
Observable.from(str);
複製程式碼
這裡由於篇幅關係,我就不貼完整程式碼了,跟just是類似的,十分簡單。
##基礎原始碼
講了兩個簡單但是常用的操作符後,我們回過頭來看一下之前的實現RxJava的程式碼,這裡我打上了Log日誌,來看一下每個方法執行的順序。
//建立Observable
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("World");
subscriber.onCompleted();
Log.i("執行順序 ---> ", " call ");
}
}).subscribe(new Observer<String>() {
@Override
public void onNext(String s) {
Log.i("onNext ---> ", s);
Log.i("執行順序 ---> ", " subscribe onNext");
}
@Override
public void onCompleted() {
Log.i("onCompleted ---> ", "完成");
Log.i("執行順序 ---> ", " subscribe onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("onError ---> ", "出錯 --->" + e.toString());
}
});
複製程式碼
好了,來看一下Log日誌:
從圖中可以看到,subscribe方法先執行,等執行完成後再執行call方法。
好了,這就是結論。先在腦子裡產生個印象,方便後面追溯。
###create()
先來看看Observable的create()方法做了些什麼?Ctrl點進去看看:
public static <T> Observable<T> create(OnSubscribe<T> f) {
return new Observable<T>(hook.onCreate(f));
}
複製程式碼
啥事沒幹,就是返回一個 Observable。
再看看它的建構函式,構造一下物件:
protected Observable(OnSubscribe<T> f) {
this.onSubscribe = f;
}
複製程式碼
再來看這個 hook.onCreate(f) 。 hook 是啥呢?
hook是一個代理物件, 僅僅用作除錯的時候可以插入一些測試程式碼。
static final RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook();
複製程式碼
注意是僅僅,所以它幾乎沒啥用處,完全可以忽略。來看 hook.onCreate(f) :
public <T> OnSubscribe<T> onCreate(OnSubscribe<T> f) {
return f;
}
複製程式碼
依然啥事沒幹,只是把 OnSubscribe 這個物件返回了一下。
OK,說到這裡,雖然我一直在強調它“啥事沒幹”,其實仔細推敲,它還真做了三件事情:
- 返回了一個Observable(假設為ObservableA)
- 返回了一個OnSubscribe(假設為OnSubscribeA)
- 把返回的OnSubscribe在Observable建構函式中儲存為Observable的 .onSubscribe 屬性
說到這裡,不知道大家看懂了沒有。我第一次看這到這裡的時候,還有略微有點模糊的,沒關係,只要模糊那就畫圖理解:
這樣看起來是不是輕鬆很多,create()就做了這樣簡單的事情,所以概括(但可能並不準確)地來說就是:
create()方法建立了一個Observable,且在這個Observable中有個OnSubscribe。
所以就畫個簡圖就如下圖所示這樣,這個圖要注意,之後還會擴充套件:
好了,create方法就分析到這裡,雖然有點囉嗦,但是已經十分詳細了。
###subscribe()
現在來看另外一個比較重要的操作 subscribe() ,在前篇文章中說過,這個是將觀察者(Observer)與被觀察者(Observable)聯絡到一起的操作,也就是產生一種訂閱(Subcribe)關係。
跟前面的一樣,先來看一下原始碼,點進去是這樣的:
public final Subscription subscribe(final Observer<? super T> observer) {
if (observer instanceof Subscriber) {
return subscribe((Subscriber<? super T>)observer);
}
return subscribe(new ObserverSubscriber<T>(observer));
}
複製程式碼
之前我們說過一句話:
實質上,在 RxJava 的 subscribe 過程中,Observer 也總是會先被轉換成一個 Subscriber 再使用。
在這裡就能夠看出,首先 if 中的語句意思是如果這個Observer已經是Subscriber型別,那就直接返回。如果不是的話 new了一個ObserverSubscriber ,再點進去看看:
public final class ObserverSubscriber<T> extends Subscriber<T> {
final Observer<? super T> observer;
public ObserverSubscriber(Observer<? super T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
observer.onNext(t);
}
@Override
public void onError(Throwable e) {
observer.onError(e);
}
@Override
public void onCompleted() {
observer.onCompleted();
}
}
複製程式碼
果然,它還是轉成了Subscriber型別,剛好印證了之前的話。所以為了方便起見,之後文章中,所有的觀察者(Observer)我都用Subscriber來代替。 這是一個小插曲,注意一下就好。
好了,繼續看 subscribe 原始碼:
public final Subscription subscribe(Subscriber<? super T> subscriber) {
return Observable.subscribe(subscriber, this);
}
private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
...
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
...
}
複製程式碼
把一些暫時無關的程式碼省略掉來看,其實就是執行了一句 hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber); 。
而這個 hook.onSubscribeStart 方法再點進去看看:
public <T> OnSubscribe<T> onSubscribeStart(Observable<? extends T> observableInstance, final OnSubscribe<T> onSubscribe) {
// pass through by default
return onSubscribe;
}
複製程式碼
可以看到,竟然直接返回了一個 onSubscribe ,由於之前說過這個hook沒什麼作用,直接刪掉,那就等於整個 subscribe 做了一件事就是 onSubscribe.call(subscriber) ,當然這個call裡面的引數subscriber是我們程式碼中傳遞進去的。
而onSubscribe在create原始碼解析中我們已經知道是新建 ObservableA 的一個屬性,所以總結來說,subscribe()方法做的事情就是這樣:
ObservableA.onSubscribe.call(subscriber);
而呼叫 call 方法,就是呼叫傳入的引數subscriber的onNext/onCompleted/onError方法。
這就是全部的過程。
看到這裡,估計大家又迷糊了。沒關係,依然畫個圖來說,圖中省略了create中的建立步驟:
結合圖我們最後再順一下思路:
- 首先建立過程也就是create()方法中建立了一個Observable,並有一個onSubscribe屬性;
- 其次在訂閱過程也就是subscribe()方法中,呼叫了create()方法中建立的Observable的onSubscribe屬性的call方法;
- 最後這個call回撥的就是程式碼中建立的Subscriber的onNext/onCompleted/onError方法。
不知道大家還記得那個Log日誌麼,從日誌可以看到,將onNext與onCompleted方法執行完後,call方法才結束。這也印證了call方法回撥Subscriber的方法這一說。
##結語
好了,終於把原始碼中比較簡單的部分講解完了,等於是再複習了一邊之前學的。
而且終於也把RxJava的入門知識講解完了。後面的文章中,就開始學如何稍微高階一點的運用RxJava,比如map/flatmap操作符、lift的原理、執行緒控制的原理、各種運用場景等等,還有很長的路要走啊。
最後這是我第一次試著講解原始碼,而且也在邊學邊分享,所以肯定有錯誤或不清楚的地方,歡迎大家指正與交流。
###參考資料
###專案原始碼
IamXiaRui-Github-FirstRxJavaDemo
個人部落格:www.iamxiarui.com