上一節我們主要講的是RxJava的入門之create的源碼解讀,讓我們對RxJava有了初步的認識,本來這篇文章應該前些天寫的,但是由於最近工作比較忙,今天晚上,不知道怎麼的失眠睡不着,於是乎想起來做點什麼,便有了現在的這篇文章。好,廢話不多說,我們現在開始進入正題。
首先我們來看下下面這些代碼:
public static void just() {
List<Integer> items = new ArrayList<>();
items.add(1);
items.add(10);
items.add(100);
items.add(200);
Observable.just(items)
.subscribe(new Observer<List<Integer>>() {
@Override
public void onCompleted() {
Log.d("test", "OnComplete");
}
@Override
public void onError(Throwable e) {
Log.d("test", e.toString());
}
@Override
public void onNext(List<Integer> integers) {
for (int i = 0; i <integers.size();i++){
Log.d("test",String.valueOf(integers.get(i)));
}
}
});
}
public static void from() {
List<Integer> items = new ArrayList<>();
items.add(1);
items.add(10);
items.add(100);
items.add(200);
Observable.from(items)
.subscribe(new Observer<Integer>() {
@Override
public void onCompleted() {
Log.d("test", "OnComplete");
}
@Override
public void onError(Throwable e) {
Log.d("test", e.toString());
}
@Override
public void onNext(Integer integers) {
Log.d("test", "Item is " + String.valueOf(integers));
}
});
}
上面主要貼的是一個just函數與一個from函數,代碼上大家看下他們具體有什麼差別。
- 我們看到傳入的都是一個list,所以打印出來的內容都是一樣的,但是默認最後都會執行onComplete這個方法,打印出OnComplete字符串。
其次subscribe這個方法中的入參just是一個list類型,from是一個Integer類型,這說明當需要循環完list中的數據時,from需要調用4次onNext,而just之需要調用一次OnNext(以本例子中list中有4個字符串爲例),所以當我們需要在一個界面展示一個list的時候,我們就應該使用just,這樣只會刷新一次界面,from的話會調用4次,最後展示的可能就不是我們想要的結果的列表。
總結了上面的結論,我們再來看下這兩個函數具體是怎麼實現的?
首先來說下from,看下圖:
我們看到from中的入參是一個Interable類型的,而很多的集合類都實現了這一個接口,比如我們前面舉例的list,繼承自Collection,而Collection是繼承自Interable的。
當我們調用from的時候,我們new了一個OnSubscribeFromIterable對象,我們知道實現OnSubscribe接口的類有好多個,OnSubscribeFromIterable便是其中的一個,調用new這個方法,我們只是把我們創建出來的list保存到了一個變量當中,這裏暫且取名爲it,然後在from這個方法裏面又調用了一個create的方法,其實這個方法,和我們上一張講過的調用的是同一個方法,如下圖所示:
調用上面的這個方法, 只是傳入一個OnSubscribe對象保存在了一個名叫OnSubscribe的變量當中,
接下來我們再來分析subScribe()過程,
和上一章講的一樣,當我們調用這個方法的時候,如下圖:
仔細的觀察這個方法,我們看到當我們傳入我們創建的obServer的時候,他只是重新創建了一個Subscriber對象,而這個對象是繼承自Observer的,我們暫且把自己創建的叫observer1,新創建的叫做observer2,看下subscribe具體的實現過程:
private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
// validate and proceed
if (subscriber == null) {
throw new IllegalArgumentException("observer can not be null");
}
if (observable.onSubscribe == null) {
throw new IllegalStateException("onSubscribe function can not be null.");
/*
* the subscribe function can also be overridden but generally that's not the appropriate approach
* so I won't mention that in the exception
*/
}
// new Subscriber so onStart it
subscriber.onStart();
/*
* See https://github.com/ReactiveX/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls
* to user code from within an Observer"
*/
// if not already wrapped
if (!(subscriber instanceof SafeSubscriber)) {
// assign to `observer` so we return the protected version
subscriber = new SafeSubscriber<T>(subscriber);
}
// The code below is exactly the same an unsafeSubscribe but not used because it would
// add a significant depth to already huge call stacks.
try {
// allow the hook to intercept and/or decorate
hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
return hook.onSubscribeReturn(subscriber);
} catch (Throwable e) {
// special handling for certain Throwable/Error/Exception types
Exceptions.throwIfFatal(e);
// if an unhandled error occurs executing the onSubscribe we will propagate it
try {
subscriber.onError(hook.onSubscribeError(e));
} catch (Throwable e2) {
Exceptions.throwIfFatal(e2);
// if this happens it means the onError itself failed (perhaps an invalid function implementation)
// so we are unable to propagate the error correctly and will just throw
RuntimeException r = new RuntimeException("Error occurred attempting to subscribe [" + e.getMessage() + "] and then again while trying to pass to onError.", e2);
// TODO could the hook be the cause of the error in the on error handling.
hook.onSubscribeError(r);
// TODO why aren't we throwing the hook's return value.
throw r;
}
return Subscriptions.unsubscribed();
}
}
其實在這寫代碼中,很多都是註釋,下面我們來看下邏輯,
1:當我們傳入observer2的時候,可以看到前面進行的一系列的判斷。2:有一個onStart方法,而這個方法在rxJava只是一個空實現,所以我們在這裏可以先不用管他。
3:把subscribe包裝成了一個SafeSubscriber對象。
4:接下來的這句話,纔是一切回調的開始,
hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber);
這裏的OnSubscribe對象,是我們第一次調用from的時候保存的OnSubscribe對象,即我們自己創建的匿名的OnSubscribe
對象,而這裏的入參,是我們第二次創建的observer2,當我們調用call方法的時候,即:
call方法被執行,開始循環遍歷值(即上面提到的it),當it中有值的時候,會調用setProducer()方法,
它也只是簡單的保存了一下值。
再來看看setProducer()方法,
傳入了一個producer對象,當經過判斷以後,會執行最下面的request方法,即剛纔傳入的IterableProducer類中的request方法,下面看下這個方法:
@Override
public void request(long n) {
if (get() == Long.MAX_VALUE) {
// already started with fast-path
return;
}
if(n==Long.MAX_VALUE&&compareAndSet(0,Long.MAX_VALUE)) {
fastpath();
} else
if(n>0&&BackpressureUtils.getAndAddRequest(this, n) == 0L) {
slowpath(n);
}
}
void slowpath(long n) {
// backpressure is requested
final Subscriber<? super T> o = this.o;
final Iterator<? extends T> it = this.it;
long r = n;
while (true) {
long numToEmit = r;
while (true) {
if (o.isUnsubscribed()) {
return;
} else if (it.hasNext()) {
if (--numToEmit >= 0) {
o.onNext(it.next());
} else
break;
} else if (!o.isUnsubscribed()) {
o.onCompleted();
return;
} else {
// is unsubscribed
return;
}
}
r = addAndGet(-r);
if (r == 0L) {
// we're done emitting the number requested so
// return
return;
}
}
}
void fastpath() {
// fast-path without backpressure
final Subscriber<? super T> o = this.o;
final Iterator<? extends T> it = this.it;
while (true) {
if (o.isUnsubscribed()) {
return;
} else if (it.hasNext()) {
o.onNext(it.next());
} else if (!o.isUnsubscribed()) {
o.onCompleted();
return;
} else {
// is unsubscribed
return;
}
}
}
}
爲什麼要有一個producer接口對象呢?在上一章create的時候,我們是直接調用了observer中的onNext的方法,因爲它發射的是一個對象,而from,我們更像是把傳入的當成一個生產者,因爲在iterable中不止一個對象。發射的是多個對象。
在這個方法中,看到有一個fastpath與一個slowpath方法(我這裏爲什麼要寫這兩個方法,也不是很明白,如果知道的,可以在下面留言,告訴我一下哈,謝謝),在這兩個方法裏,都會去循環調用observer2中的onNext的方法,而observer2中的onNext的方法中又會去調用observer1中的方法,也就是我們自己寫的方法,這樣就完成了整個回調,而最後爲什麼會執行onComplete方法是因爲當迭代結束的時候,會執行onComplete方法,
最後在subscribe方法中return了一個Subscription對象,是方便我們unSubscribe,可以防止內存溢出。
下面我們來總結一下,
**1. 我們創建了OnSubscribe對象,
2. 我們創建了observer1
3. 創建了observer2
4. subscribe方法調用OnSubscribe中的call方法
5. 創建一個producer對象
6. producer循環發射list中的數據,不斷調用observer2中的onNext
7. observer2調用observer1中的onNext
8. 最後調用onComplete方法結束調用**
以上就是from的知識,感覺有點長,just方法的實現,請看下一節。