核心问题:
- 为甚是被观察者订阅观察者
- RxJava执行的流程
- 线程切换的原理
为甚是被观察者订阅观察者
Observable.subscribe(Observer); 从字面上的理解是被观察者订阅观察者,比如报纸订阅了读者。但从开发者的角度来理解,就很正常 了。
RxJava这样设置的目的是为了流式Api的设计,还有就是Android中的观察者模式都是这样的写法,比如View.setOnClickListener(OnClickListener) : View就是被观察者,OnClickListener是观察者,他们通过setOnClickListener形成订阅关系。 一旦被观察者发生了什么事情(事件),就需要告知观察者,然后观察者会做出相应的措施。
RxJava执行的流程
从一个简单的示例代码说起:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
private Disposable mD = null;
@Override
public void onSubscribe(Disposable d) {
mD = d;
}
@Override
public void onNext(Integer value) {
if (1 == value) {
mD.dispose();
}
}
@Override
public void onError(Throwable e) {
KLog.d("e:" + e.toString());
}
@Override
public void onComplete() {
KLog.d("onComplete");
}
});
按照自上而下的顺序,开始吧
Observable.create(ObservableOnSubscribe<T> source)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
流程的第一步,创建了两个对象:ObservableOnSubscribe 和 ObservableCreate 。
ObservableCreate
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
//省略其他代码
}
ObservableCreate 继承Observable,在构造函数中保存了上一级创建的 ObservableOnSubscribe 对象的引用。
public abstract class Observable<T> implements ObservableSource<T>{...}
public interface ObservableSource<T> {
void subscribe(Observer<? super T> observer);
}
上面的2段源码清楚的看到,Observable 是一个抽象类,是 ObservableSource 的实现类,而 ObservableSource 类是一个接口,它表示事件源。内部只有一个方法 subscribe 该方法表示通过 Observer 订阅当前的事件源。那么事件发布的事件,在 Observer 订阅者中就会被收到。了解了 Observable 的顶层接口之后,我们就知道该体系最重要的一个功能那就是 subscribe 方法了,因此我们就重点关注子类的 subscribe 方法。
现在,把视角转到Observable的subscribe()方法来,看看它做了什么处理。
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
//这段代码是核心代码
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
protected abstract void subscribeActual(Observer<? super T> observer);
他把observer订阅者传递给subscribeActual(Observer observer)抽象方法,这意味着所有Observable的子类,我们只要关心 subscribeActual(observer); 这个方法就好的。
好的,那么我们就回到最开始的ObservableCreate,去看看他在subscribeActual()做了什么
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
在上面的代码里面,先是创建了一个发射器CreateEmitter,然后回调给 observer#onSubscribe() ,最后是通知上一级的Observable(也就是代码里的source)你可以发送事件了。这边不太了解RxJava可能有疑问我为什么这么下定论?因为事件是在被观察者“订阅”观察者时后才发送的!!!
subscribeOn(Schedulers.io())
这个方法的作用是让上游事件切换线程的,不管它在整个流中使用了几次,只有第一次是有效的。why? 先把这个疑问放下,后面看看流程图就应该明白了。
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
}
//省略部分代码
}
是不是很熟悉,因为AbstractObservableWithUpstream也是继承自Observable。subscribeActual()方法里执行的也是相似的逻辑,只不过是多了scheduler线程相关的逻辑,这里先不进行详细分析。
abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
/** The source consumable Observable. */
protected final ObservableSource<T> source;
/**
* Constructs the ObservableSource with the given consumable.
* @param source the consumable Observable
*/
AbstractObservableWithUpstream(ObservableSource<T> source) {
this.source = source;
}
@Override
public final ObservableSource<T> source() {
return source;
}
}
这个抽象类也是保存了上一个Observable的引用。
observeOn(AndroidSchedulers.mainThread())
我猜这边应该是相似的代码。
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 {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
//省略相关代码
}
果不其然,就不赘述了。
subscribe(Observer observer)
subscribe后,被观察者(Observable)一旦有发射什么事件,观察者(Observer)都可以接收事件。
总结
过程:断点调试,绘制流程图
[图片上传失败...(image-cd3051-1524734258521)]
还记得在介绍 #subscribeOn(Schedule)方法提出的那个问题?
无论我们在整个上游的事件流中使用了多少次#subscribeOn(Schedule)变换线程,只有第一次设置的有效。看了上面的流程图,相信应该明白了吧。
怎么进行线程切换的
subscribeOn(Schedulers.io())
首先了解下Scheduler.io()方法,它返回的是一个Scheduler,Scheduler是一个抽象方法,我们知道抽象方法是不能被实例化的,那么返回的肯定是它的实现类:
public static Scheduler io() {
return RxJavaPlugins.onIoScheduler(IO);
}
上面代码里的IO对象是什么呢?
IO = RxJavaPlugins.initIoScheduler(new Callable<Scheduler>() {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
}
});
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
答案是IoScheduler对象。
在前面的学习中,我们知道了subscribeOn(Schedulers.io())返回的对象是ObservableSubscribeOb对象
public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new Runnable() {
@Override
public void run() {
source.subscribe(parent);
}
}));
}
source.subscribe(parent) 被放在一个Runnable中执行,那么他是否已经就在子线程执行了呢?
NO,NO,NO,这还得看Runnable是被放在哪个线程上的,说不定是mainThread呢。
先看看scheduleDirect方法
//无延迟执行
public Disposable scheduleDirect(Runnable run) {
return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
}
scheduleDirect.java
public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
//createWorker是一个抽象方法,创建一个可以可以执行 run 的 worker
final Worker w = createWorker();
//对 run 进行了包装,实际上还是 run 这个对象
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
//decoratedRun 交给了 worker 去执行
w.schedule(new Runnable() {
@Override
public void run() {
try {
decoratedRun.run();
} finally {
w.dispose();
}
}
}, delay, unit);
return w;
}
直指IoScheduler#createWorker()
@Override
public Worker createWorker() {
return new EventLoopWorker(pool.get());
}
EventLoopWorker.java
static final class EventLoopWorker extends Scheduler.Worker {
//省略部分code
@Override
public Disposable schedule(Runnable action, long delayTime, TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}
}
EventLoopWorker extends Scheduler.Worker ,Worker这个抽象类有个schedule()抽象方法需要重写,所以这个类的核心逻辑就在schedule()方法里:==threadWorker.scheduleActual(action, delayTime, unit, tasks);== ,点击进去看看:
public class NewThreadWorker extends Scheduler.Worker implements Disposable {
//executor 是一个线程池
private final ScheduledExecutorService executor;
volatile boolean disposed;
public NewThreadWorker(ThreadFactory threadFactory) {
executor = SchedulerPoolFactory.create(threadFactory);
}
//省略部分代码
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, TimeUnit unit, DisposableContainer parent) {
//对传进来的run进行包装
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
//拿到f,传给ScheduledRunnable
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
parent.remove(sr);
RxJavaPlugins.onError(ex);
}
return sr;
}
ScheduledRunnable里面又做了什么?
@Override
public void run() {
try {
try {
//actual就是通过构造函数传递进来的Runnable
actual.run();
} catch (Throwable e) {
// Exceptions.throwIfFatal(e); nowhere to go
RxJavaPlugins.onError(e);
}
} finally {
Object o = get(PARENT_INDEX);
if (o != DISPOSED && o != null && compareAndSet(PARENT_INDEX, o, DONE)) {
((DisposableContainer)o).delete(this);
}
for (;;) {
o = get(FUTURE_INDEX);
if (o == DISPOSED || compareAndSet(FUTURE_INDEX, o, DONE)) {
break;
}
}
}
}
“故事”的最终还是交给actual.run()去执行,也就是执行==source.subscribe(parent);== 几经“旋转跳跃”,它投入了子线程的怀抱。
小结
切换到子线程的逻辑还是比较容易的,利用线程池而已....
observeOn(AndroidSchedulers.mainThread())
首先了解下AndroidSchedulers.mainThread()
/** A {@link Scheduler} which executes actions on the Android main thread. */
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}
private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
new Callable<Scheduler>() {
@Override public Scheduler call() throws Exception {
return MainHolder.DEFAULT;
}
});
private static final class MainHolder {
static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
}
可以清楚的知道AndroidSchedulers.mainThread()返回的Schedule类是HandlerScheduler,内持有一个可以在主线程发送消息的handler对象。
接下来将代码定位到ObservableObserveOn#subscribeActual()方法
protected void subscribeActual(Observer<? super T> observer) {
//TrampolineScheduler是在当前线程执行的,但不是立即执行,需要等当前的工作单元都执行结束后。
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//这个schedule是HandlerScheduler,创建了一个 Scheduler.Worker
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
ObserveOnObserver
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
//划重点!
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
==getAndIncrement() == 0== 是校验没有原子性,没有多个任务在同时执行
scheduler.createWorker()做了什么?
HandlerScheduler
@Override
public Worker createWorker() {
return new HandlerWorker(handler);
}
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, Math.max(0L, 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;
}
//省略部分代码
}
在HandlerWorker#schedule()方法里通过Handler发送Message,Message中的callback对应run对象。
我们都知道Handler发送消息后会在dispatchMessage()方法处理
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
清楚的看到了业务逻辑执行==message.callback.run();== 也就是说ScheduledRunnable会被执行,ScheduledRunnable是ObserveOnObserver#schedule()方法里被传入的。
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
它传入的是this,那么最终执行的是ObserveOnObserver#run()方法了。
@Override
public void run() {
//outputFused默认值为false
if (outputFused) {
drainFused();
} else {
drainNormal();
}
}
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
final Observer<? super T> a = actual;
for (;;) {
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
for (;;) {
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
s.dispose();
q.clear();
a.onError(ex);
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
a.onNext(v);
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
自上而下看了过来,找到了 ==a.onNext(v);== ,记住它现在所在的是主线程。
小结
- 1、==AndroidSchedulers.MainThread()==,这个Scheduler(HandlerScheduler)它持有在主线程执行的Handle。
- 2、ObserveOn返回的对象是==ObservableObserveOn==,封装了一个持有原观察者的Observer(ObserveOnObserver),它实现了Runnable接口,当执行到onNext()时,执行了Scheduler.Worker#schedule(Runnable)方法,并把this传递进去了。
- HandlerScheduler.HandlerWorker#schedule()方法里用handle发送Message,而这个Message的callback就是之前传递进来的this(Runnable),最终在dispathMessage()方法里得到了执行,也就是执行run方法。回调到ObservableObserveOn.Observer#run()方法执行actual.onNext(),因为handle所在的线程是主线程,所以onNext(T t)所在的线程也是主线程。
一句话总结RxJava子线程和主线程的原理
切换到子线程的关键是将Runnable放到线程池去执行,切换到主线程是利用在主线程实例化的Handle发送Message,让runnable回调到主线程去。