背景
RxJava是一个在Android开发中广泛使用的响应式编程库,它提供了强大的工具和模式来处理异步事件流。然而,RxJava的强大功能和灵活性往往会导致一些开发者陷入误区。有些开发者可能会过度使用,将其应用于不适合的场景,导致代码变得复杂难懂。此外,错误的使用方式可能会导致性能问题和内存泄漏等。因此,我们需要深入阅读源码并理解其原理。
基本组件
RxJava 的核心原理其实非常简单。可类比观察者模式。Observable是被观察者,作为数据源产生数据。Observer是观察者,消费上游的数据源。
每个Observable可注册多个Observer。但是默认情况下,每当有注册发生时,Observable的生产方法subscribe都会被调用。如果想只生产一次,可以调用Observable.cached方法。
被观察者Observable还有多个变体,如Single、Flowable。Single代表只产生一个元素的数据源。Flowable是支持背压的数据源。通过背压设计,下游监听者可以向上游反馈信息,可以达到控制发送速率的功能。
Observable和Observer是通过装饰器模式层层包装达到从而串联起来。转换API如map等,会创建一个新的ObservableMap基层自Observable,包装原始的Observable作为source,而在真正执行时,先做转换操作,再发给下游的观察者。
Scheduler是RxJava为多线程执行提供的支持类,它将可以将生产者或者消费者的执行逻辑包装成一个Worker,提交到框架提供的公共线程池中,如Schedulers.io()、Schedulers.newThread()等。便于理解,可以将Schedulers类比做线程池,Worker类比做线程池中的线程。可以通过 Observable.subscribeOn和Observable.observeOn分别制定被观察者和观察者执行的线程,来达到异步非阻塞。
RxJava 核心架构图如下:
基本原理
RxJava 的代码,观察者模式和装饰器模式。为了便于理解核心原理,我们写了几个简版的Rxjava框架类。
// 返回的子类是ObservableCreate
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("test");
emitter.onComplete();
}
});
// 订阅observable
observable.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println(Thread.currentThread().getName() + " , onSubscribe");
}
@Override
public void onNext(String s) {
System.out.println(Thread.currentThread().getName() + " ,s = " + s);
}
@Override
public void onError(Throwable e) {}
@Override
public void onComplete() {
System.out.println(Thread.currentThread().getName() + " , onComplete");
}
});
Observable--被观察者的核心抽象类
public abstract class Observable<T> implements ObservableSource<T> {
@Override
public void subscribe(Observer<T> observer) {
// 和谁建立订阅?
// 怎么建立订阅?
// 为了保证拓展性,交给具体的开发人员实现。这里提供一个抽象的方法
subscribeActual(observer);
}
protected abstract void subscribeActual(Observer<T> observer);
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
return new ObservableCreate<>(source);
}
public ObservableSubscribeOn<T> subscribeOn(Scheduler scheduler) {
return new ObservableSubscribeOn<>(this, scheduler);
}
public ObservableObserveOn<T> observeOn(Scheduler scheduler) {
return new ObservableObserveOn<>(this, scheduler);
}
}
Observable是一个抽象类,定义了subscribe这个final方法,最终会调用 subscribeActual(observer);而subscribeActual是由子类实现的方法,自然我们需要看ObserverableCreate内部的具体实现。 ObservableCreate
public class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@Override
protected void subscribeActual(Observer<T> observer) {
CreateEmitter<T> emitter = new CreateEmitter<T>(observer);
observer.onSubscribe();
source.subscribe(emitter);
}
static class CreateEmitter<T> implements Emitter<T> {
Observer<T> observer;
boolean done;
public CreateEmitter(Observer<T> observer) {
this.observer = observer;
}
@Override
public void onNext(T t) {
if (done) return;
observer.onNext(t);
}
@Override
public void onError(Throwable throwable) {
if (done) return;
observer.onError(throwable);
done = true;
}
@Override
public void onComplete() {
if (done) return;
observer.onComplete();
done = true;
}
}
}
ObserverableCreate,它包装了一个source对象,即传入的ObserverableOnSubscribe。
@Override
protected void subscribeActual(Observer<T> observer) {
CreateEmitter<T> emitter = new CreateEmitter<T>(observer);
observer.onSubscribe();
source.subscribe(emitter);
}
- 将观察者observer包装到一个CreateEmitter里。
- 调用observer的onSubscribe方法。
- 调用source(即生产代码接口)的subscribe方法,传入这个emitter。
第二步中,直接调用了我们写的消费者的onSubscribe方法,很好理解,即创建订阅关系的回调方法。重点在第三步,source.subscribe(parent);这个parent是包装了observer的emitter。还记得source就是我们写的发送事件的代码。其中手动调用了emitter.onNext()来发送数据。那么我们CreateEmitter.onNext()做了什么?
@Override
public void onNext(T t) {
if (done) return;
observer.onNext(t);
}
done对应源码的!isDisposed(),判断订阅关系。observer.onNext(t)这个observer就是我们写的消费者。以上就是RxJava最基本的原理,其实逻辑很简单,就是在创建订阅关系的时候,直接调用生产逻辑代码,然后再生产逻辑的onNext中,调用了观察者observer.onNext。
线程调度
理解了上面的调用逻辑,很自然可以明白。subscribeOn通过层层包装,最终的实现是ObservableSubscribeOn,observeOn最终的实现是ObservableObserveOn。类似的,我们来看下内部的具体实现,我们以ObservableObserveOn为例,便于理解,依然是简版的Rxjava框架类。
...
.subscribeOn(Schedulers.io())// 主要来决定我执行subscribe方法所处的线程,也就是产生事件发射事件所在的线程
.observeOn(AndroidSchedulers.mainThread())// 来决定下游事件被处理时所处的线程
...
ObservableObserveOn--调度下游的执行的线程
public class ObservableObserveOn<T> extends AbstractObservableWithUpStream<T, T> {
final Scheduler scheduler;
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
@Override
protected void subscribeActual(Observer<T> observer) {
Scheduler.Worker worker = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<>(observer, worker));
}
static final class ObserveOnObserver<T> implements Observer<T>, Runnable {
final Observer<T> downSteam;
final Scheduler.Worker worker;
final Deque<T> queue;
volatile boolean done;
volatile Throwable error;
volatile boolean over;
public ObserveOnObserver(Observer<T> downSteam, Scheduler.Worker worker) {
this.downSteam = downSteam;
this.worker = worker;
queue = new ArrayDeque<>();
}
@Override
public void onSubscribe() {
downSteam.onSubscribe();
}
@Override
public void onNext(T t) {
queue.offer(t);// 把事件加入队列,offer不抛异常,只会返回false
schedule();
}
private void schedule() {
worker.schedule(this);
}
@Override
public void onComplete() {}
@Override
public void onError(Throwable throwable) {}
@Override
public void run() {
drainNormal();
}
/**
* 从队列中排放事件并处理
*/
private void drainNormal() {
final Deque<T> q = queue;
final Observer<T> a = downSteam;
while (true) {
boolean d = done;
T t = q.poll();// 取出数据,没有数据的时候不会抛异常,返回null
boolean empty = t == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
a.onNext(t);
}
}
private boolean checkTerminated(boolean d, boolean empty, Observer<T> a) {
if (over) {
queue.clear();
return true;
}
if (d) {
Throwable e = error;
if (e != null) {
over = true;
a.onError(error);
return true;
} else if (empty) {
over = true;
a.onComplete();
return true;
}
}
return false;
}
}
}
- 最终生产者代码中调用onNext时,会调用schedule方法。
- schedule方法中,会提交自身(ObserveOnObserver)到线程池。
- 而run方法会调用onNext(emitter)。
可见,RxJava 线程调度的机制就是通过observeOn(Scheduler)将发送元素的代码onNext(emitter)提交到线程池里执行。