谜之RxJava (三)—— 线程切换

【谜之RxJava (二) —— Magic Lift】javascript

Rxjava -- 一个异步库

RxJava最迷人的是什么?
答案就是把异步序列写到一个工做流里!javascriptPromise/A一模一样。
OK,在java中作异步的事情在咱们传统理解过来可不方便,并且,若是要让异步按照咱们的工做流来,就更困难了。java

可是在RxJava中,咱们只要调用调用
subscribOn()observeOn()就能切换咱们的工做线程,是否是让小伙伴都惊呆了?android

而后结合RxJavaOperator,写异步的时候,想切换线程就是一行代码的事情,整个workflow还很是清晰:segmentfault

Observable.create()
// do something on io thread
.work() // work.. work..
.subscribeOn(Schedulers.io())
// observeOn android main thread
.observeOn(AndroidSchedulers.mainThread())
.subscribe();

咱们不再用去写什么见鬼的new ThreadHandler了,在这么几行代码里,咱们实现了在io线程上作咱们的工做(work),在main线程上,更新UI异步

Subscribe On

先看下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);
}

咱们这里不要记TR,记住传入左边的模板是形参,传入右边的模板是返回值

好了,那么这里的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当中生成的那个地方。

咱们知道这一层liftoperator就是刚刚的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就是上一层ObservableonSubscribe,即Observable<Observable<T>>onSubscribe,至关于栈弹出了一层。它的call直接在SubscriberonNext中给出了最开始的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便可。结合扔物线大大的图以下:
rxjavarxjava_12.png

总结

这里逻辑着实很差理解。若是尚未理解的朋友,能够按照我前文说的顺序,细致的看下来,我把逻辑过一遍以后,发现lift的陷阱实在太大,内部类用的风生水起,一不当心,就不知道一个变量的上下文是什么,须要特别当心。

迷之RxJava(四)—— Retrofit和RxJava的基情

本文在不停更新中,若是有不明白的地方(可能会有不少),请你们给出意见,拍砖请轻点= =

相关文章
相关标签/搜索