RxJava Source Parsing 05-Thread Switching
In this article, we will analyze the switching of Rx Java threads.
Observable.just("123") .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { } });
subscribeOn
The observaOn acts on the operator until a new observeOn operator appears and switches when Observer.onNext, onCompleted, and onError occur. subscribeOn can switch multiple times.
subscribeOn
SubscribeOn acts on the Observable creation operator and the doOnSubscribe operator before the operator. When subscribeOn has more than one, only the first one is valid (except doSubscriber, doSubscribe is called before OnSubscribe.call).
Switch on Onsubscribe.call()
subscribeOn source code parsing
public final Observable<T> subscribeOn(Scheduler scheduler, boolean requestOn) { if (this instanceof ScalarSynchronousObservable) { return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler); } return unsafeCreate(new OperatorSubscribeOn<T>(this, scheduler, requestOn)); }
Look at Operator Subscribe On
@Override public void call(final Subscriber<? super T> subscriber) { final Worker inner = scheduler.createWorker(); SubscribeOnSubscriber<T> parent = new SubscribeOnSubscriber<T>(subscriber, requestOn, inner, source); subscriber.add(parent); subscriber.add(inner); inner.schedule(parent); }
Schduler. createWorker () is called here; Worker is created and schedule is called. This scheduler is passed in by the constructor, which is the parameter passed in by calling subscribeOn().
Take a look at Schedulers.newThread(), and trace the source code to find that it's the NewThreadScheduler class.
public final class NewThreadScheduler extends Scheduler { private final ThreadFactory threadFactory; public NewThreadScheduler(ThreadFactory threadFactory) { this.threadFactory = threadFactory; } @Override public Worker createWorker() { return new NewThreadWorker(threadFactory); } }
Mainly from NewThreadWorker
public NewThreadWorker(ThreadFactory threadFactory) { ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, threadFactory); boolean cancelSupported = tryEnableCancelPolicy(exec); if (!cancelSupported && exec instanceof ScheduledThreadPoolExecutor) { registerExecutor((ScheduledThreadPoolExecutor)exec); } executor = exec; }
You can see that the thread pool is created here, and then look at the scheme method.
@Override public Subscription schedule(final Action0 action, long delayTime, TimeUnit unit) { if (isUnsubscribed) { return Subscriptions.unsubscribed(); } return scheduleActual(action, delayTime, unit); } 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; }
You can see that executor.submit() is called here. action is the parent object passed in by Operator SubscribeOn. schedule, which is a subclass of Action0 and eventually calls parent.call. Parent is SubscribeOn Subscriber
@Override public void call() { //... src.unsafeSubscribe(this); //src is subscribe }
Thus onNext, onCompleted and onError are already executed in the switched threads, thus realizing the switching of threads.
@Override public void onNext(T t) { actual.onNext(t); } @Override public void onError(Throwable e) { try { actual.onError(e); } finally { worker.unsubscribe(); } } @Override public void onCompleted() { try { actual.onCompleted(); } finally { worker.unsubscribe(); } }
ObeOn Source Code Analysis
After some methods, Observer#observeOn() is called.
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) { //... return lift(new OperatorObserveOn<T>(scheduler, delayError, bufferSize)); }
The lift method converts the incoming T to R, where Operator ObserveOn inherits from Operator
summary
RxJava's thread switching is actually based on Scheduler generated by Schedulers, and ultimately calls the corresponding thread pool for thread switching.
If it's Android Schedulers. mainThread, it uses Handler to switch to the main thread.
class LooperScheduler extends Scheduler { //... @Override public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) { if (unsubscribed) { return Subscriptions.unsubscribed(); } action = hook.onSchedule(action); ScheduledAction scheduledAction = new ScheduledAction(action, handler); Message message = Message.obtain(handler, scheduledAction); message.obj = this; // Used as token for unsubscription operation. handler.sendMessageDelayed(message, unit.toMillis(delayTime)); if (unsubscribed) { handler.removeCallbacks(scheduledAction); return Subscriptions.unsubscribed(); } return scheduledAction; } //... }