rxjava中的线程转换
rxjava的线程转换可通过observeOn()或subscribeOn()来进行,通常情况下observeOn()是用来指定Observer处理事件的线程,而subscribeOn()则指定Observable的call()进行的线程。
我们跳进observeOn()方法里,可以看到这方法最终会调用到这里。
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
if (this instanceof ScalarSynchronousObservable) {
return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
}
return lift(new OperatorObserveOn<T>(scheduler, delayError, bufferSize));
}
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return unsafeCreate(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
可以看到和map()一样,都是重新创建了一个Observable返回,其中lift()方法中onSubscribe是指调用ObserveOn()方法的Observable的OnSubscribe对象。我们先看看在observeOn方法里的OperatorObserveOn类是个什么东西。
public final class OperatorObserveOn<T> implements Operator<T, T>
public interface Operator<R, T> extends Func1<Subscriber<? super R>, Subscriber<? super T>>
OperatorObserveOn最终继承自Func1类,且可以看出他是对Subscriber进行加工的,这里可以预测到线程的调度将会是在这个类里面进行。既然是继承自Func1类,那么重点关注call()这个方法。
@Override
public Subscriber<? super T> call(Subscriber<? super T> child) {
if (scheduler instanceof ImmediateScheduler) {
// avoid overhead, execute directly
return child;
} else if (scheduler instanceof TrampolineScheduler) {
// avoid overhead, execute directly
return child;
} else {
ObserveOnSubscriber<T> parent = new ObserveOnSubscriber<T>(scheduler, child, delayError, bufferSize);
parent.init();
return parent;
}
}
可以看到在第二个else里面重新创建了一个Subscriber返回,那么这个Subscriber就是关键所在了。
static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0
我们首先看其onNext()方法。
public void onNext(final T t) {
if (isUnsubscribed() || finished) {
return;
}
if (!queue.offer(NotificationLite.next(t))) {
onError(new MissingBackpressureException());
return;
}
schedule();
}
和map()不同,这里并没有选择去调用下方Subscriber的,而是调用了自身的schedule()方法,这方法实际上就是进行线程的切换,这里根据传入的Scheduler对象不同会有不同的实现,这里以Schedulers.IO为例,最终将会调用到NewThreadWorker类的scheduleActual()方法中,而在这方法里会通过线程池在另一个线程中最终调用之前传入进去的Action0的call()方法,从而实现线程的转化。
public ScheduledAction scheduleActual(final Action0 action, long delayTime, TimeUnit unit) {
Action0 decoratedAction = RxJavaHooks.onScheduledAction(action);
ScheduledAction run = new ScheduledAction(decoratedAction);
Future<?> f;
if (delayTime <= 0) {
f = executor.submit(run);
} else {
f = executor.schedule(run, delayTime, unit);
}
run.add(f);
return run;
}
那这个Action0对象是什么?我们可以注意到之前新创建的Subscriber是实现了Action0接口的,并且也最终会调用到新创建的Subscriber的call()方法上,我们观察这个call()方法。
public void call() {
...
while (requestAmount != currentEmission) {
boolean done = finished;
Object v = q.poll();
boolean empty = v == null;
if (checkTerminated(done, empty, localChild, q)) {
return;
}
if (empty) {
break;
}
localChild.onNext(NotificationLite.<T>getValue(v));
currentEmission++;
if (currentEmission == limit) {
requestAmount = BackpressureUtils.produced(requested, currentEmission);
request(currentEmission);
currentEmission = 0L;
}
}
...
}
可以看到在16行那里调用了下方Subscriber的onNext,成功将事件传递了过去,并且也成功换了线程。
subscribeOn()方法和observeOn()类似,只不过线程调度的方法放在了新创建的Observable的call()方法里面,而不是在Subscriber里面。
总的来说rxjava线程转换和其map()方法类似,会再创建一个Observable,然后在这个Observable里面或对应的新创建的Subscriber里面实现线程转换,并且如果不再进行转换,那么之后的行为将默认在该线程里面执行。