【謎之RxJava (二) —— Magic Lift】javascript
RxJava
最迷人的是什麼?
答案就是把異步序列寫到一個工做流裏!
和javascript
的Promise/A
一模一樣。
OK,在java
中作異步的事情在咱們傳統理解過來可不方便,並且,若是要讓異步按照咱們的工做流來,就更困難了。java
可是在RxJava
中,咱們只要調用調用subscribOn()
和observeOn()
就能切換咱們的工做線程,是否是讓小夥伴都驚呆了?android
而後結合RxJava
的Operator
,寫異步的時候,想切換線程就是一行代碼的事情,整個workflow
還很是清晰:segmentfault
Observable.create() // do something on io thread .work() // work.. work.. .subscribeOn(Schedulers.io()) // observeOn android main thread .observeOn(AndroidSchedulers.mainThread()) .subscribe();
咱們不再用去寫什麼見鬼的new Thread
和Handler
了,在這麼幾行代碼裏,咱們實現了在io
線程上作咱們的工做(work
),在main
線程上,更新UI異步
先看下subscribeOn
幹了什麼ide
public final Observable<T> subscribeOn(Scheduler scheduler) { if (this instanceof ScalarSynchronousObservable) { return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler); } return nest().lift(new OperatorSubscribeOn<T>(scheduler)); }
啊,原來也是個lift,就是從一個Observable
生成另一個Observable
咯,這個nest
是幹嗎用?函數
public final Observable<Observable<T>> nest() { return just(this); }
這裏返回類型告訴咱們,它是產生一個Observable<Observable<T>>
講到這裏,會有點暈,先記着這個,而後咱們看OperatorSubscribeOn
這個操做符,post
構造函數是this
public OperatorSubscribeOn(Scheduler scheduler) { this.scheduler = scheduler; }
OK,這裏保存了scheduler
對象,而後就是咱們前一章說過的轉換方法。spa
@Override public Subscriber<? super Observable<T>> call(final Subscriber<? super T> subscriber) { final Worker inner = scheduler.createWorker(); subscriber.add(inner); return new Subscriber<Observable<T>>(subscriber) { @Override public void onCompleted() { // ignore because this is a nested Observable and we expect only 1 Observable<T> emitted to onNext } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(final Observable<T> o) { inner.schedule(new Action0() { @Override public void call() { final Thread t = Thread.currentThread(); o.unsafeSubscribe(new Subscriber<T>(subscriber) { @Override public void onCompleted() { subscriber.onCompleted(); } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(T t) { subscriber.onNext(t); } @Override public void setProducer(final Producer producer) { subscriber.setProducer(new Producer() { @Override public void request(final long n) { if (Thread.currentThread() == t) { // don't schedule if we're already on the thread (primarily for first setProducer call) // see unit test 'testSetProducerSynchronousRequest' for more context on this producer.request(n); } else { inner.schedule(new Action0() { @Override public void call() { producer.request(n); } }); } } }); } }); } }); } }; }
看完這段又臭又長的,先深呼吸一口氣,咱們慢慢分析下。
首先要注意RxJava
裏面最讓人頭疼的模板問題,那麼OperatorMap
這個類的聲明是
public final class OperatorMap<T, R> implements Operator<R, T>
而Operator
這個接口繼承Func1
public interface Func1<T, R> extends Function { R call(T t); }
咱們這裏不要記T
和R
,記住傳入左邊的模板是形參,傳入右邊的模板是返回值
。
好了,那麼這裏的
call
就是從一個T
轉換成一個Observable<T>
的過程了。
總結一下,咱們這一次調用subscribeOn
,作了兩件事
一、
nest()
爲Observable<T>
生成了一個Observable<Observable<T>>
二、lift()
對Observalbe<Observalbe<T>>
進行一個變化,變回Observable<T>
由於lift
是一個模板函數,它的返回值的類型是參照它的形參來,而他的形參是Operator<T, Observable<T>>
這個結論很是重要!!
OK,到這裏咱們已經存儲了全部的序列,等着咱們調用了。
首先,記錄咱們在調用這條指令以前的Observable<T>
,記爲Observable$1
而後,通過lift
生成的Observable<T>
記爲Observable$2
好了,如今咱們拿到的依然是Observable<T>
這個對象,可是它不是原始的Observable$1
,要深深記住這一點,它是由lift
生成的Observable$2
,這時候進行subscribe
,那看到首先調用的就是OnSubscribe.call
方法,好,直接進入lift
當中生成的那個地方。
咱們知道這一層lift
的operator
就是剛剛的OperatorSubscribOn
,那麼調用它的call
方法,生成的是一個Subscriber<Observable<T>>
Subscriber<? super T> st = hook.onLift(operator).call(o); try { // new Subscriber created and being subscribed with so 'onStart' it st.onStart(); onSubscribe.call(st); } catch (Throwable e) { ... }
好,還記得咱們調用過nest
麼?,這裏的onSubscribe
但是nest
上下文中的噢,每一次,到這個地方,這個onSubscribe
就是上一層Observable
的onSubscribe
,即Observable<Observable<T>>
的onSubscribe
,至關於棧彈出了一層。它的call
直接在Subscriber
的onNext
中給出了最開始的Observable<T>
,咱們這裏就要看下剛剛在OperatorSubscribeOn
中生成的Subscriber
new Subscriber<Observable<T>>(subscriber) { @Override public void onCompleted() { // ignore because this is a nested Observable and we expect only 1 Observable<T> emitted to onNext } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(final Observable<T> o) { inner.schedule(new Action0() { @Override public void call() { final Thread t = Thread.currentThread(); o.unsafeSubscribe(new Subscriber<T>(subscriber) { @Override public void onCompleted() { subscriber.onCompleted(); } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(T t) { subscriber.onNext(t); } }); } }); } }
對,就是它,這裏要注意,這裏的subscriber
就是咱們在lift
中,傳入的o
Subscriber<? super T> st = hook.onLift(operator).call(o);
對,就是它,其實它就是SafeSubscriber
。
回過頭,看看剛剛的onNext()
方法,inner.schedule()
這個函數,咱們能夠認爲就是postRun()
相似的方法,而onNext()
中傳入的o
是咱們以前生成的Observable$1
,是從Observable.just
封裝出來的Observable<Observable<T>>
中產生的,這裏調用了Observable$1.unsafeSubscribe
方法,咱們暫時不關心它和subscribe
有什麼不一樣,可是咱們知道最終功能是同樣的就行了。
注意它運行時的線程!!在
inner
這個Worker
上!因而它的運行線程已經被改了!!
好,這裏的unsafeSubscribe
調用的方法就是調用原先Observable$1.onSubscribe
中的call
方法:
這個Observable$1
就是咱們以前本身定義的Observable
了。
綜上所述,若是咱們須要咱們的Observable$1
在一個別的線程上運行的時候,只須要在後面跟一個subscribeOn
便可。結合扔物線大大的圖以下:
這裏邏輯着實很差理解。若是尚未理解的朋友,能夠按照我前文說的順序,細緻的看下來,我把邏輯過一遍以後,發現lift
的陷阱實在太大,內部類用的風生水起,一不當心,就不知道一個變量的上下文是什麼,須要特別當心。
迷之RxJava(四)—— Retrofit和RxJava的基情
本文在不停更新中,若是有不明白的地方(可能會有不少),請你們給出意見,拍磚請輕點= =