RxJava
在项目开发中用得还是比较多的,它能将复杂的嵌套调用转为链式调用,减轻代码的复杂性,方便于代码的后期维护工作。用得多了,自然想看下内部的实现原理,毕竟这么牛逼的框架,其内部的实现思想也是值得学习的,再者之前面试问到了RxJava的原理。所以这里就来记录下(代码基于2.x),也方便后续复习。
基本使用
Observable.just("1")
.subscribe(object : Observer<String>{
override fun onComplete() {}
override fun onSubscribe(d: Disposable) {}
override fun onNext(t: String) {}
override fun onError(e: Throwable) {}
})
上游可以通过Observable的操作符just
发送事件,Observable有很多操作符,也可以根据业务需要自定义操作符。订阅观察者通过subscribe
方法,它有多个重载方法,可以根据情况使用。上游发送的事件,下游就可以在onNext
方法中获取结果。
执行原理
先看下RxJava的UML类图
明白了继承结构,接下来对上面的Demo进行原理分析
- just()
public static <T> Observable<T> just(T item) {
ObjectHelper.requireNonNull(item, "The item is null");
return RxJavaPlugins.onAssembly(new ObservableJust<T>(item)); //1
}
Observable的just操作符在注释1处,会创建一个ObservableJust对象,参数为item。然后传入RxJavaPlugins的onAssembly方法,它是一个钩子函数,具体看实现
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
默认情况下f为null,会直接返回source。也就是说还是会返回ObservableJust,它是抽象类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); //1
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
...
}
}
订阅方法subscribe它的实现在Observable中,而这个方法内部会调用subscribeActual方法。它是一个抽象方法,具体实现会在子类中。而刚刚调用just操作符返回了ObservableJust对象,所以subscribeActual具体实现在ObservableJust中
@Override
protected void subscribeActual(Observer<? super T> s) {
ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value); //1
s.onSubscribe(sd);
sd.run(); //2
}
这个s就是在使用时候创建的Observer对象,它会和value封装到ScalarDisposable中,然后在注释2调用run方法
@Override
public void run() {
if (get() == START && compareAndSet(START, ON_NEXT)) {
observer.onNext(value); //1
if (get() == ON_NEXT) {
lazySet(ON_COMPLETE);
observer.onComplete(); //2
}
}
}
在run方法中,注释1处会调用onNext方法,这样下游就可以收到事件了,回调onNext。事件发送完毕之后会发送onComplete通知发送完毕。
线程切换
对于RxJava用得比较多的地方就是做异步操作,比如数据库和网络请求,分析源码时候先写一个简单的使用
Observable.just("1")
.subscribeOn(Schedulers.io()) //1
.observeOn(AndroidSchedulers.mainThread()) //2
.subscribe(object : Observer<String>{
override fun onComplete() {}
override fun onSubscribe(d: Disposable) {}
override fun onNext(t: String) {}
override fun onError(e: Throwable) {}
})
关键代码在注释1和2处,注释1让被观察者运行在io线程,注释2让观察者运行在主线程
先看注释1,跟进io()方法
public static Scheduler io() {
return RxJavaPlugins.onIoScheduler(IO);
}
IO是一个静态变量,赋值代码为
IO = RxJavaPlugins.initIoScheduler(new IOTask());
这段代码最后是返回IoHolder.DEFAULT
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
最后返回的也就是IoScheduler
对象,这个对象后面会用到,先记着
再来看subscribeOn方法
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
刚刚的IoScheduler传入这个方法,并传入ObservableSubscribeOn对象,构建返回给下一级调用。
再来看注释2,跟进mainThread()方法
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;
}
});
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}
最后的MainHolder.DEFAULT
是HandlerScheduler,并封装了一个主线程的Handler,这里就可以猜到线程切换就是通过Handler完成的。
两个线程切换的操作符分析完了,接着从整体调用流程来看RxJava的线程切换过程。整个流程代码切换过程分为三步
第一步,很简单,Observable->ObservableJust->ObservableSubscribeOn->ObservableObserveOn
第二步,订阅观察者,处理事件,通过subscribed()订阅观察者,内部会调用ObservableObserveOn的subscribeActual方法
@Override
protected void subscribeActual(Observer<? super T> observer) {
...
Scheduler.Worker w = scheduler.createWorker(); //1
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize)); //2
}
注释1处的scheduler是刚刚分析的HandlerScheduler对象,所以createWorker()方法的实现
public Worker createWorker() {
return new HandlerWorker(handler);
}
w也就是HandlerWorker对象,封装到ObserveOnObserver中。
接着调用到ObservableSubscribeOn的subscribed,然后调用subscribeActual方法
@Override
public void subscribeActual(final Observer<? super T> s) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s); //1
s.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent))); //2
}
这个方法里面的参数s就是ObserveOnObserver对象,注释1处会再对它封装,然后传入注释2处的SubscribeTask,它是一个Runnable,传入的parent只是做了一个赋值操作。
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
然后看scheduleDirect方法,这里的scheduler就是IoScheduler,然后看下这个方法的实现,它的实现在父类Scheduler中
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
final Worker w = createWorker(); //1
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run); //2
DisposeTask task = new DisposeTask(decoratedRun, w); //3
w.schedule(task, delay, unit); //4
return task;
}
先跟进这里的注释1,
public Worker createWorker() {
return new EventLoopWorker(pool.get());
}
返回了一个EventLoopWorker对象
参数run就是SubscribeTask,它会被包装进DisposeTask对象,它也是一个Runnable对象。接着到注释4
public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (tasks.isDisposed()) {
// don't schedule, we are unsubscribed
return EmptyDisposable.INSTANCE;
}
return threadWorker.scheduleActual(action, delayTime, unit, tasks);
}
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
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) {
//1
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
关键代码在注释1处,参数run是会被封装到一个ScheduledRunnable对象中赋值为sr,然后放入一个线程池中,那么前面的SubscribeTask的run就会执行,代码切换到了子线程,再来回顾下它的run方法中
public void run() {
source.subscribe(parent);
}
这个source是ObservableJust,它里面会调用到它的subscribeActual方法
protected void subscribeActual(Observer<? super T> s) {
ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
s.onSubscribe(sd);
sd.run();
}
s就是SubscribeOnObserver。事件处理完之后,就开始向下游发送事件
第三步
@Override
public void onNext(T t) {
actual.onNext(t);
}
这个actual就是ObserveOnObserver,看下它的onNext方法
public void onNext(T t) {
...
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
这里的worker是HandlerWorker对象,跟进这个方法在HandlerWorker对象中的实现,
@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;
}
这里很明显的可以看到通过将Runnable封装到一个Message对象中,然后通过Handler向创建Handler所在线程发送了一个消息,这个Handler持有主线程的mainLooper,所以代码会切回主线程,后面的就是将事件在主线程发送给下游的onNext回调。
总结:线程切换被观察者是通过一个线程池切换到子线程,被观察者事件处理完之后,向下游发送事件,然后通过Handler切换回主线程。
执行流程
看完RxJava的原理,其实套路也明白了,上游在通过Observable调用不同操作符时候,返回的是Observable子类,再调用多个操作符时候,其实也是返回Observable子类,并且将上一个Observable对象传给下一个操作符,不同的操作符其功能是不同的,这样做的目的是为了适配多场景的使用。当遇到subscribe方法时候,用来订阅观察者。subscribe是在抽象类Observable中,它内部会调用subscribeActual方法,而不同的操作符返回的都是Observable的具体实现,它们都会实现subscribeActual方法。在这个方法内部也会对Observer包装,然后调用上一个Observable的subscribe方法,直到最上游,处理事件,然后向下游发送事件。举上面为例子,大致流程如下:
使用别的操作符调用也是差不多这个理