<a href="http://www.reibang.com/p/808b09d1b5ab">RxJava 從入門到愛(ài)上它 - 認(rèn)識(shí)</a>
<a href="http://www.reibang.com/p/f4af4752cd26">RxJava 從入門到愛(ài)上它 - 源碼分析線程控制</a>
關(guān)于Backpressure 作者也將在后續(xù)的文章中做出解析燕耿。
"變換"的理解(RxJava真正的核心)
RxJava中常用的"變換"
RxJava中的所有的操作 map
自点、flatMap
、groupBy
跺株、scan
苍日、concat
等等 (這些操作方法的具體使用請(qǐng)看另一篇文章) 都是一種"變換"宅楞。為了更好地實(shí)現(xiàn)復(fù)雜的鏈?zhǔn)讲僮髡胱耍覀兙托枰獊?lái)好好解析下它的工作原理了。
RxJava"變換"的原理
這是map()
的源碼(源碼版本為RxJava1.1.6)厌衙,其中調(diào)用了"變換"的核心方法left()
距淫,我們先來(lái)分析下這段代碼:
//Observable.java
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return lift(new OperatorMap<T迅箩, R>(func));
}
public final <R> Observable<R> lift(final Operator<? extends R溉愁, ? super T> operator) {
return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe饲趋, operator));
}
//OnSubscribeLift.java
@Override
public void call(Subscriber<? super R> o) {
try {
Subscriber<? super T> st = hook.onLift(operator).call(o);
try {
// new Subscriber created and being subscribed with so 'onStart' it
st.onStart();
parent.call(st);
} catch (Throwable e) {
// localized capture of errors rather than it skipping all operators
// and ending up in the try/catch of the subscribe method which then
// prevents onErrorResumeNext and other similar approaches to error handling
Exceptions.throwIfFatal(e);
st.onError(e);
}
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// if the lift function failed all we can do is pass the error to the final Subscriber
// as we don't have the operator available to us
o.onError(e);
}
}
通過(guò)上面的源碼我們可以得知"變換"left()
的流程如下(有些代碼沒(méi)有列出拐揭,此處不再贅述,感興趣的朋友可以去Github上詳細(xì)看下):
通過(guò)hook.onLift(operator)
執(zhí)行封裝的操作奕塑,通過(guò)call()
傳入原始Subscriber
然后封裝成新的Subscriber
堂污,然后通知父Observable
來(lái)處理這個(gè)新的Subscriber
。
簡(jiǎn)述:
- 創(chuàng)建一個(gè)新的
Observable
(被觀察者)- 新的
Observable
的call()
中
a. 通過(guò)Operator
來(lái)創(chuàng)建一個(gè)新的Subscriber
(觀察者)龄砰。
b. 調(diào)用父Observable
的call
方法通知它對(duì)新創(chuàng)建的Subscriber
進(jìn)行處理盟猖。
- 新的
我們通過(guò)下面的一個(gè)例子來(lái)理解下整個(gè)鏈?zhǔn)讲僮鞯牧鞒蹋?/p>
Observable.just("hello"讨衣, "my", "name"式镐, "is"反镇, "nichool")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return "map: " + s;
}
})
.map(new Func1<String娘汞, String>() {
@Override
public String call(String s) {
return "map1: " + s;
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
LogUtils.LogW(s);
}
});
先預(yù)想下將會(huì)打印的Log是什么4醪琛!.
上面的代碼可以分成下面這幾個(gè)流程:
執(zhí)行流程時(shí)序圖中(A)操作: 也就是剛才的left()
的簡(jiǎn)述
時(shí)序圖(B)操作:Observable2.subscribe()
將注冊(cè)的Subscriber
傳入并調(diào)用call()
你弦,開始通知流程
通知流程時(shí)序圖中操作:
(C) : 調(diào)用Observable2.call() - ( 就是left()
中call
方法)生成新的Subscriber subscriber2 然后調(diào)用Observable1.call();
(D) : 調(diào)用Observable1.call() - 生成 subscriber1惊豺,調(diào)用 Observable.call();
(E) : 調(diào)用Observable.call() - 將封裝了所有操作的subscriber1傳入call方法中,開始發(fā)送流程
發(fā)送流程時(shí)序圖中操作:
(F) : 調(diào)用subscriber1 中的onNext 等方法
(I) : 調(diào)用subscriber2 中的onNext 等方法
(J) : 調(diào)用subscriber(此處為上面代碼中的subscribe()方法中的Subscriber) 中的onNext 等方法
整個(gè)流程合起來(lái)的流程圖 (圖片來(lái)自 https://gank.io/post/560e15be2dca930e00da1083#toc_15):
這是結(jié)果的Log
RxJavaDemo: map1: map: hello
RxJavaDemo: map1: map: my
RxJavaDemo: map1: map: name
RxJavaDemo: map1: map: is
RxJavaDemo: map1: map: nichool
總結(jié)
RxJava中"變換"的核心就是將操作封裝成新的觀察者禽作,多個(gè)”變換“的鏈?zhǔn)讲僮饕簿褪嵌鄠€(gè)觀察者與被觀察者相互通知與處理的流程尸昧,整個(gè)RxJava項(xiàng)目通過(guò)這種代理的思想來(lái)實(shí)現(xiàn)復(fù)雜的邏輯。(真心厲害?醭ァE胨住!)
本文的分析將非常有助于線程調(diào)度方面的理解@晖薄衷蜓!
分析過(guò)程中如若存在錯(cuò)誤,請(qǐng)?jiān)谙路皆u(píng)論處給予指正尘喝。
↓↓↓↓↓如果覺(jué)得可以的話,請(qǐng)點(diǎn)擊下面的喜歡斋陪⌒嗤剩或者打賞哦,我會(huì)更加努力的无虚〉拊↓↓↓↓↓