又是一个令人激动的东西,真不想说废话了,开始神奇之旅吧(原谅我这么土鳖,就是觉得很神奇,不看不知道,一看吓一跳啊)
灵活的变换已经让我们眼花缭乱了,线程的自由控制更是让RxJava的牛叉之气更上一层楼。
前边我们已经知道了可以利用subscribeOn()结合observeOn()来实现线程控制,让事件的产生和消费发生在不同的线程,map() flatMap()等方法都可以多次变换,那线程切换能不能多次呢?
答案当然是能啦,因为observeOn指定的是Subscriber的线程,而这个Subscriber并不一定是(此处可较真,理解为 不是)subscribe()参数中的Subscriber,而是observeOn()执行时的当前observable所对应的Subscriber,即它的直接下级Subscriber,换句话说,observeOn()指定的是它之后的操作所在的线程,因此,如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次observeOn()即可。
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.map(mapOperator) // 新线程,由 observeOn() 指定
.observeOn(Schedulers.io())
.map(mapOperator2) // IO 线程,由 observeOn() 指定
.observeOn(AndroidSchedulers.mainThread)
.subscribe(subscriber); // Android 主线程,由 observeOn() 指定
不同于observeOn(),subscribeOn()的位置放哪里都可以,但是它只能调用一次,那如果非要调用多次呢,这个问题我们从线程控制的原理开始说起吧
Scheduler原理:
subscribeOn()和observeOn()的内部实现,也是用了lift()方法,
先看observeOn()吧:
public final Observable<T> observeOn(Scheduler scheduler) {
if (this instanceof ScalarSynchronousObservable) {
return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
}
return lift(new OperatorObserveOn<T>(scheduler));
}
这里分为了两种情况,第一种情况Observable是由just方法创建的,我们看看他的走向:
public Observable<T> scalarScheduleOn(Scheduler scheduler) {
if (scheduler instanceof EventLoopsScheduler) {
EventLoopsScheduler es = (EventLoopsScheduler) scheduler;
return create(new DirectScheduledEmission<T>(es, t));
}
return create(new NormalScheduledEmission<T>(scheduler, t));
}
这里可以看到根据Scheduler的类型又分为两种情况,不过都是创建一个新的Observable<T>对象。那么不同的就是两个OnSubscribe<T>对象了,一个是DirectScheduledEmission,另一个是NormalScheduleEmission。
/** Optimized observeOn for scalar value observed on the EventLoopsScheduler. */
static final class DirectScheduledEmission<T> implements OnSubscribe<T> {
private final EventLoopsScheduler es;
private final T value;
DirectScheduledEmission(EventLoopsScheduler es, T value) {
this.es = es;
this.value = value;
}
@Override
public void call(final Subscriber<? super T> child) {
child.add(es.scheduleDirect(new ScalarSynchronousAction<T>(child, value)));
}
}
/** Emits a scalar value on a general scheduler. */
static final class NormalScheduledEmission<T> implements OnSubscribe<T> {
private final Scheduler scheduler;
private final T value;
NormalScheduledEmission(Scheduler scheduler, T value) {
this.scheduler = scheduler;
this.value = value;
}
@Override
public void call(final Subscriber<? super T> subscriber) {
Worker worker = scheduler.createWorker();
subscriber.add(worker);
worker.schedule(new ScalarSynchronousAction<T>(subscriber, value));
}
}
/** Action that emits a single value when called. */
static final class ScalarSynchronousAction<T> implements Action0 {
private final Subscriber<? super T> subscriber;
private final T value;
private ScalarSynchronousAction(Subscriber<? super T> subscriber,
T value) {
this.subscriber = subscriber;
this.value = value;
}
@Override
public void call() {
try {
subscriber.onNext(value);
} catch (Throwable t) {
subscriber.onError(t);
return;
}
subscriber.onCompleted();
}
}
。。。。。。。再来看一下subscribeOn()
public final Observable<T> subscribeOn(Scheduler scheduler) {
if (this instanceof ScalarSynchronousObservable) {
return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
}
return nest().lift(new OperatorSubscribeOn<T>(scheduler));
}
这里我不想先分析第一种情况了,先来看第二种情况吧:
nest()函数干了啥:
public final Observable<Observable<T>> nest() {
return just(this);
}
so easy,调用了just方法,但是请注意,这里的this,把最原始的这个Observable当做参数传入了,
public final static <T> Observable<T> just(final T value) {
return ScalarSynchronousObservable.create(value);
}
还是来复习看一下这个ScalarSynchronousObservable吧
public final class ScalarSynchronousObservable<T> extends Observable<T> {
public static final <T> ScalarSynchronousObservable<T> create(T t) {
return new ScalarSynchronousObservable<T>(t);
}
private final T t;
protected ScalarSynchronousObservable(final T t) {
super(new OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> s) {
/*
* We don't check isUnsubscribed as it is a significant performance impact in the fast-path use cases.
* See PerfBaseline tests and https://github.com/ReactiveX/RxJava/issues/1383 for more information.
* The assumption here is that when asking for a single item we should emit it and not concern ourselves with
* being unsubscribed already. If the Subscriber unsubscribes at 0, they shouldn't have subscribed, or it will
* filter it out (such as take(0)). This prevents us from paying the price on every subscription.
*/
s.onNext(t);
s.onCompleted();
}
});
this.t = t;
} // 暂且省略无关代码
看到这个ScalarSynchronousObservable对象,我们此时需要记住的是:原始Observable被当做一个属性保存在ScalarSynchronousObservable对象中,看图:
以上是nest()函数调用以后发生的事情,接着开始看lift()函数:先复习一下原来我们分析的lift原理图:
lift方法会创建一个Observable<T>对象,该对象的内部有一个OnSubscribe<T>对象,它的call方法会调用OperatorSubscribeOn.call方法得到一个Subscriber<Observable<T>>对象,并在调用上面的Observable<Observable<T>>.OnSubscribe<Observable<T>>.call方法时传递进去。那么来看下OperatorSubscribeOn.call是如何将一个Subscribe<T>转换成Subscriber<Observable<T>>对象的。
public class OperatorSubscribeOn<T> implements Operator<T, Observable<T>> {
private final Scheduler scheduler;
public OperatorSubscribeOn(Scheduler scheduler) {
this.scheduler = scheduler;
}
@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);
}
});
}
}
});
}
});
}
});
}
};
}
}
可以看到OperatorSubscribeOn对象的call方法里面实例化了一个Subscriber<T>对象并返回。该Subscriber<T>的onNext方法中会调用Scheduler.schedule将一个Action0加入线程池里执行,该Action0的call方法会触发原始Observable<T>的unsafeSubscribe方法,然后会触发原始OnSubscribe<T>.call方法,也就是说原始OnSubscribe<T>.call方法是在切换后的线程中执行。如图