内容简介:在上一篇博客接下来,我们先来回顾一下,Observable 与 Observer 之间是如何订阅的简单来说就是,当我们调用 Observable 的 subsribe 方法的时候,会调用当前对应 observbale 的 subscribeActual 方法,在该方法里面,会调用 observer 的 onSubeciber 方法,并调用对应 ObservableOnSubscirbe 的 subcribe 的方法,并将 ObservableEmitter 作为方法参数暴露出去。而 ObservableEm
在上一篇博客 Rxjava 2.x 源码系列 - 线程切换 (上) 我们讲解到,Observable#subscribeOn 是如何控制上游 Observable 的执行线程的,他的实质是将 Observable#subscribe(Observer) 的操作放在了指定线程,当我们调用 subcribe 的时候,它的过程是从下往上的,即下面的 Observable 调用上面的 Observable。用下面的流程图表示如下。
接下来,我们先来回顾一下,Observable 与 Observer 之间是如何订阅的
简单来说就是,当我们调用 Observable 的 subsribe 方法的时候,会调用当前对应 observbale 的 subscribeActual 方法,在该方法里面,会调用 observer 的 onSubeciber 方法,并调用对应 ObservableOnSubscirbe 的 subcribe 的方法,并将 ObservableEmitter 作为方法参数暴露出去。而 ObservableEmitter 持有我们的 Observer 的引用,当我们调用 ObservableEmitter 的 onNext,onErrot,onComplete 方法的时候,会调用他持有的 Observer 的相应的方法。
这篇博客主要讲解以下问题:
- observeOn 是如何控制 Observer 的回调线程的
Observable#observeOn 方法
@CheckReturnValue @SchedulerSupport(SchedulerSupport.CUSTOM) public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) { ObjectHelper.requireNonNull(scheduler, "scheduler is null"); ObjectHelper.verifyPositive(bufferSize, "bufferSize"); return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize)); } 复制代码
observeOn 的套路跟 Observable.create 方法的套路基本一样,都是先判断是否为空,不为 null,用一个新的类包装起来,并持有上游的引用 source。这里我们的包装类是 ObservableObserveOn。
这里我们来看一下 ObservableObserveOn
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> { final Scheduler scheduler; final boolean delayError; final int bufferSize; public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) { super(source); this.scheduler = scheduler; this.delayError = delayError; this.bufferSize = bufferSize; } @Override protected void subscribeActual(Observer<? super T> observer) { // 如果是当前线程,直接低啊用 if (scheduler instanceof TrampolineScheduler) { source.subscribe(observer); } else { // 否则,通过 worker 的形式调用 Scheduler.Worker w = scheduler.createWorker(); source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); } } } 复制代码
从第一篇博客 Rxjava 2.x 源码系列 - 基础框架分析 ,我们知道,当我们调用 Observable.subscibe(observer) 方法的时候,会调用到 对应的 Observable 实例的 subscribeActual 方法,而这里我们的 Observable 为 ObservableObserveOn 。
在 ObservableObserveOn.subscribeActual 方法中,首先会判断 scheduler instanceof TrampolineScheduler (是否是当前线程),true 的话,会直接调用 source.subscribe(observer)。否则,先用 ObserveOnObserver 包装 observer,再调用 source.subscribe 方法
接下来,我们一起来看一下 ObserveOnObserver 类
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T> implements Observer<T>, Runnable { final Observer<? super T> actual; } public abstract class BasicIntQueueDisposable<T> extends AtomicInteger implements QueueDisposable<T> { 复制代码
ObserveOnObserver 继承于 BasicIntQueueDisposable,实现 Observer, Runnable 接口,而 BasicIntQueueDisposable extends AtomicInteger ,是原子操作类。
其中,还有一个很重要的属性 actual ,即是实际的 observer。 复制代码
接下来,我们来看一下几个重要的方法:
onNext,onError,onComplete,onSubscribition
public void onSubscribe(Disposable s) { if (DisposableHelper.validate(this.s, s)) { ------- if (m == QueueDisposable.SYNC) { sourceMode = m; queue = qd; done = true; actual.onSubscribe(this); schedule(); return; } if (m == QueueDisposable.ASYNC) { sourceMode = m; queue = qd; actual.onSubscribe(this); return; } } queue = new SpscLinkedArrayQueue<T>(bufferSize); actual.onSubscribe(this); } } @Override public void onNext(T t) { if (done) { return; } ------ schedule(); } @Override public void onError(Throwable t) { if (done) { RxJavaPlugins.onError(t); return; } ---- schedule(); } @Override public void onComplete() { if (done) { return; } ---- schedule(); } 复制代码
在 onNext,onError,onComplete 方法中首先都会先判断是否 done,如果没有的话,会调用 schedule() 方法。
void schedule() { if (getAndIncrement() == 0) { worker.schedule(this); } } 复制代码
而在 schedule() 方法中,直接调用 Worker 的 schedule 方法,这样就会执行我们当前 ObserveOnObserver 的 run 方法,
public void run() { if (outputFused) { drainFused(); } else { drainNormal(); } } 复制代码
在 drainFused 和 drainNormal 方法中,会根据状态去调用 actual(外部传入的 observer) 的 onNext、onError、onComplete 方法。因此 observer 的回调所在的线程将取决于外部传入的 scheduler 的 schedule 方法所在的线程。
假设我们传入的是 observeOn(AndroidSchedulers.mainThread())
public final class AndroidSchedulers { private static final class MainHolder { static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper())); } private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler( new Callable<Scheduler>() { @Override public Scheduler call() throws Exception { return MainHolder.DEFAULT; } }); /** A {@link Scheduler} which executes actions on the Android main thread. */ public static Scheduler mainThread() { return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD); } --- } 复制代码
private static final class HandlerWorker extends Worker { private final Handler handler; private volatile boolean disposed; HandlerWorker(Handler handler) { this.handler = handler; } @Override public Disposable schedule(Runnable run, long delay, TimeUnit unit) { if (run == null) throw new NullPointerException("run == null"); if (unit == null) throw new NullPointerException("unit == null"); if (disposed) { return Disposables.disposed(); } run = RxJavaPlugins.onSchedule(run); ScheduledRunnable scheduled = new ScheduledRunnable(handler, run); Message message = Message.obtain(handler, scheduled); message.obj = this; // Used as token for batch disposal of this worker's runnables. handler.sendMessageDelayed(message, unit.toMillis(delay)); // Re-check disposed state for removing in case we were racing a call to dispose(). if (disposed) { handler.removeCallbacks(scheduled); return Disposables.disposed(); } return scheduled; } } 复制代码
从上面的分析我们知道 observer 的回调所在的线程将取决于外部传入的 scheduler 的 schedule 方法所在的线程。即 指定 observeOn(AndroidSchedulers.mainThread()) 之后,将取决于 HandlerWorker 的 schedule 方法执行的线程,在该方法中,很明显执行于主线程。
总结
控制 Observer 的回调实际是放到 ObservableObserveOn 的 run 方法中,即 ObservableObserveOn 的 run 执行在主线程, Observer 的回调也发生在主线程,而 ObservableObserveOn 的 run 执行在哪个线程,取决于 外部传入的 scheduler。因此, 当外部传入的 scheduler 的 schedule 方法在主线程,那么 observer 也在主线程回调。
扫一扫,欢迎关注我的公众号。如果你有好的文章,也欢迎你的投稿。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【重回基础】线程池源码剖析:Worker工作线程
- Java 多线程(五)—— 线程池基础 之 FutureTask源码解析
- iOS源码解析:多线程
- JStorm 源码解析:基础线程模型
- EventBus源码剖析(3) — 线程模式
- 线程池的使用和源码剖析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Rework
Jason Fried、David Heinemeier Hansson / Crown Business / 2010-3-9 / USD 22.00
"Jason Fried and David Hansson follow their own advice in REWORK, laying bare the surprising philosophies at the core of 37signals' success and inspiring us to put them into practice. There's no jarg......一起来看看 《Rework》 这本书的介绍吧!