這篇文章已經寫的很詳細了。但是畢竟是別人的東西 ,既然是學習筆記,我當然要寫寫自己的總結或者摘要,剔除那些不需要的話
https://github.com/ReactiveX/RxJava
https://github.com/ReactiveX/RxAndroid
本人感覺只要掌握了 map 和 flatmap 其實就已經可以算入門了
一.RxJava的觀察者模式
- 上一篇已經寫了兩個demo 來重溫 傳統觀察者模式 還有Rxjava的配置Rxjava 學習筆記(一)
- Rxjava 是什麼 –> 異步
Rxjava 優點 –> 簡潔,在一條鏈上(鏈式編程),當然最重要的是可以用來裝逼!!!裝逼!裝逼!裝逼!重要的事情說三篇!
RxJava 有四個基本概念:
Observable
(可觀察者,即被觀察者)、Observer
(觀察者)、subscribe
(訂閱)、事件。Observable
和Observer
通過subscribe()
方法實現訂閱關係,從而Observable
可以在需要的時候發出事件來通知Observer
RxJava的觀察者模式:
onNext(param)
onCompleted()
onError(error)
Observable ——————> Observer
二.基本實現
- 步驟:創建Observer(觀察者),創建Observable(被觀察者),Subscribe(訂閱)
1)創建Observer(觀察者)
Observer<String> observer = new Observer<String>() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
除了 Observer 接口之外,RxJava 還內置了一個實現了 Observer 的抽象類:Subscriber。 Subscriber 對 Observer 接口進行了一些擴展,但他們的基本使用方式是完全一樣的:
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
不僅基本使用方式一樣,實質上,在 RxJava 的 subscribe 過程中,Observer 也總是會先被轉換成一個 Subscriber 再使用
。所以如果你只想使用基本功能,選擇 Observer 和 Subscriber 是完全一樣的。它們的區別對於使用者來說主要有兩點:
onStart()
: 這是 Subscriber 增加的方法。它會在 subscribe 剛開始,而事件還未發送之前被調用,可以用於做一些準備工作,例如數據的清零或重置
。這是一個可選方法,默認情況下它的實現爲空。需要注意的是,如果對準備工作的線程有要求(例如彈出一個顯示進度的對話框,這必須在主線程執行), onStart() 就不適用了,因爲它總是在 subscribe 所發生的線程被調用,而不能指定線程。要在指定的線程來做準備工作,可以使用 doOnSubscribe()
方法,具體可以在後面的文中看到。
unsubscribe()
: 這是 Subscriber 所實現的另一個接口 Subscription 的方法,用於取消訂閱
。在這個方法被調用後,Subscriber 將不再接收事件。一般在這個方法調用前,可以使用 isUnsubscribed() 先判斷一下狀態。 unsubscribe() 這個方法很重要,因爲在 subscribe() 之後, Observable 會持有 Subscriber 的引用,這個引用如果不能及時被釋放,將有內存泄露的風險。所以最好保持一個原則:要在不再使用的時候儘快在合適的地方(例如 onPause() onStop() 等方法中)調用 unsubscribe() 來解除引用關係,以避免內存泄露的發生。
2)創建Observable(被觀察者)
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Hello");
subscriber.onNext("Hi");
subscriber.onNext("Aloha");
subscriber.onCompleted();
}
});
create() 方法是 RxJava 最基本的創造事件序列的方法。基於這個方法, RxJava 還提供了一些方法用來快捷創建事件隊列,例如:
just(T...)
: 將傳入的參數依次發送出來。
Observable observable = Observable.just("Hello", "Hi", "Aloha");
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
from(T[]) / from(Iterable<? extends T>)
: 將傳入的數組或 Iterable 拆分成具體對象後,依次發送出來。
String[] words = {"Hello", "Hi", "Aloha"};
Observable observable = Observable.from(words);
// 將會依次調用:
// onNext("Hello");
// onNext("Hi");
// onNext("Aloha");
// onCompleted();
3) Subscribe (訂閱)
observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);
有人可能會注意到, subscribe() 這個方法有點怪:它看起來是『observalbe 訂閱了 observer / subscriber』而不是『observer / subscriber 訂閱了 observalbe』,這看起來就像『雜誌訂閱了讀者』一樣顛倒了對象關係。這讓人讀起來有點彆扭,不過如果把 API 設計成 observer.subscribe(observable) / subscriber.subscribe(observable) ,雖然更加符合思維邏輯,但對流式 API 的設計就造成影響了,比較起來明顯是得不償失的。
Observable.subscribe(Subscriber) 的源代碼
public final Subscription subscribe(Subscriber<? super T> subscriber) {
// 首先進入這個方法,返回Subscription,好像是爲了方便 取消訂閱
return Observable.subscribe(subscriber, this);
}
private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
if (subscriber == null) {
throw new IllegalArgumentException("observer can not be null");
}
if (observable.onSubscribe == null) {
throw new IllegalStateException("onSubscribe function can not be null.");
}
// ☆ 在這裏調用了onStart()
subscriber.onStart();
// 轉換爲SafeSubscriber 不知道爲什麼轉爲他 但是看名字應該是安全的意思,無非就是做了些安全的操作,懶得往下看
if (!(subscriber instanceof SafeSubscriber)) {
subscriber = new SafeSubscriber<T>(subscriber);
}
try {
// hook.onSubscribeStart(observable, observable.onSubscribe)--> return onSubscribe
// ☆ 所以相當於調用了onSubscriber 的 call 方法
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
// 下面其實他就是直接返回 subscriber 沒有做別的操作
return hook.onSubscribeReturn(subscriber);
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// 如果執行onSubscribe出現未處理的錯誤,我們會傳播的
try {
subscriber.onError(hook.onSubscribeError(e));
} catch (Throwable e2) {
// 表示調用本身的onError失敗 , 所以就 throw 出去
Exceptions.throwIfFatal(e2);
RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
// TODO 這邊標記爲TODO ,其實看他的源碼他是直接返回了r,並沒有做什麼事情,我們其實可以在這邊自定義導致錯誤的錯誤處理
hook.onSubscribeError(r);
// TODO why aren't we throwing the hook's return value.
throw r;
}
return Subscriptions.unsubscribed(); // 取消訂閱
}
}
可以看到,subscriber() 做了3件事:
>
1. 調用 Subscriber.onStart() 。這個方法在前面已經介紹過,是一個可選的準備方法。
2. 調用 Observable 中的 OnSubscribe.call(Subscriber) 。在這裏,事件發送的邏輯開始運行。從這也可以看出,在 RxJava 中, Observable 並不是在創建的時候就立即開始發送事件,而是在它被訂閱的時候,即當 subscribe() 方法執行的時候。
3. 將傳入的 Subscriber 作爲 Subscription 返回。這是爲了方便 unsubscribe().
不完整定義的回調
除了 subscribe(Observer)
和 subscribe(Subscriber)
,subscribe()
還支持不完整定義的回調,RxJava 會自動根據定義創建出 Subscriber 。形式如下:
Action1<String> onNextAction = new Action1<String>() {
// onNext()
@Override
public void call(String s) {
Log.d(tag, s);
}
};
Action1<Throwable> onErrorAction = new Action1<Throwable>() {
// onError()
@Override
public void call(Throwable throwable) {
// Error handling
}
};
Action0 onCompletedAction = new Action0() {
// onCompleted()
@Override
public void call() {
Log.d(tag, "completed");
}
};
// 自動創建 Subscriber ,並使用 onNextAction 來定義 onNext()
observable.subscribe(onNextAction);
// 自動創建 Subscriber ,並使用 onNextAction 和 onErrorAction 來定義 onNext() 和 onError()
observable.subscribe(onNextAction, onErrorAction);
// 自動創建 Subscriber ,並使用 onNextAction、 onErrorAction 和 onCompletedAction 來定義 onNext()、 onError() 和 onCompleted()
observable.subscribe(onNextAction, onErrorAction, onCompletedAction);
簡單解釋一下這段代碼中出現的 Action1
和Action0
。 Action0
是 RxJava 的一個接口,它只有一個方法 call()
,這個方法是無參無返回值的;由於 onCompleted()
方法也是無參無返回值的,因此Action0
可以被當成一個包裝對象,將 onCompleted()
的內容打包起來將自己作爲一個參數傳入 subscribe()
以實現不完整定義的回調。這樣其實也可以看做將 onCompleted()
方法作爲參數傳進了 subscribe()
,相當於其他某些語言中的『閉包』。 Action1 也是一個接口,它同樣只有一個方法 call(T param)
,這個方法也無返回值,但有一個參數;與 Action0
同理,由於onNext(T obj)
和 onError(Throwable error)
也是單參數無返回值的,因此 Action1
可以將 onNext(obj)
和 onError(error)
打包起來傳入 subscribe()
以實現不完整定義的回調。事實上,雖然Action0
和 Action1
在 API 中使用最廣泛,但 RxJava 是提供了多個 ActionX 形式的接口 (例如 Action2
, Action3
) 的,它們可以被用以包裝不同的無返回值的方法。