基本用法
Observable observable = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(@NonNull ObservableEmitter emitter) throws Exception {
emitter.onNext(123);
emitter.onComplete();
}
});
Observer observer = new Observer() {
@Override
public void onSubscribe(@NonNull Disposable d) {
LogUtils.d("onSubscribe");
}
@Override
public void onNext(@NonNull Integer o) {
System.out.println(o);
}
@Override
public void onError(@NonNull Throwable e) {
System.out.println(e.getMessage());
}
@Override
public void onComplete() {
LogUtils.d("onComplete");
}
};
observable.subscribe(observer);
我们以这段简单的代码为基础,讲解下贯穿整个ReactiveX设计的四个概念:观察者,被观察者,事件,订阅。
- 观察者
对事件进行响应的对象,也可以称作消费者,在上述的代码中,subscirbe方法有很多个重载,其参数要么是一个Consumer对象,要么是一个Observer对象,Consumer对象后续也会被包装成一个LambdaObserver对象。因此可以说subscribe方法的参数即为Observer(观察者)。 - 被观察者
产生事件的对象,也可以称作生产者,在上述代码中,Observable.create(...)返回的是一个Observable对象,即为这段程序的被观察者(生产者)。 - 事件
RxJava中存在四种事件流:onSubscribe(订阅事件),onNext(正常事件),onError(异常事件),onComplete(完成事件)。在上述代码中,是将一个整型元素作为onNext事件中的数据进行发送。 - 订阅
创建观察者与被观察者之间观察关系,对应着上述代码中的subscribe()方法。RxJava的事件驱动模型是一种“拉模型”,在观察者没有进行事件订阅之前是不会有事件产生的,只有观察者进行订阅后,才会触发被观察者生产事件。
集大成者Observable
在整个数据处理的过程中,Observable可以说是最重要的一个对象。客户端(消息的生产者或者消费者)只和Observable进行交互,观察者和被观察者之间关系的创建也是由Observable去实现,而不用我们显示的编码实现,这大大降低了我们使用观察者模式的成本。
从图中我们可以看出:
Observable实现了ObservableSource接口,该接口中只有一个方法:
subscribe()
。从字面意思就可以理解,这是一个提供观察能力的接口,所以Observable的一大能力是供观察者进行事件订阅,而进行事件订阅的方法实现就是调用Observable的subscribe()
方法Observable是一个抽象类,它提供了
subscribeActual
模板方法供子类实现,从源码中可以看出,Observable的subscribe()
方法最终会委托子类的subscribeActual()
方法实现,这个方法会建立生产者与消费者之间的关联关系。除此之外,Observable还是一个工厂类,它提供了静态方法
fromArray()
、create()
等用来创建具体的可观察对象,同时还提供了flatMap()
、concatMap()
等操作方法对可观察对象进行包装。
Observable的存在让生产者和消费者完全的解耦了,生产者只需关注自己生成何种Observable对象,而消费者也只需关注自己观察的是哪种Observable。
在实际的应用中,Rxjava已经提供了各种各样的操作符供我们使用,生产者只需要调用Observable中相应的方法即可以生成所需的可观察对象,供消费者进行事件订阅。消费者只需调用可观察对象的subscribe()
方法即可与生产者建立观察关系,极其方便。
真实的观察
观察者模式是RxJava设计的核心思想,在观察者模式中总是存在观察的对象和被观察的对象,从上文的解析中也可以看出Observable更多的是一个控制器的作用,而并非真正的事件的来源。那么在RxJava中,什么才是真正的生产者,什么才是真正的消费者呢。
我们来分析下以下三种常见的Observable:
Observable arrayObservable = Observable.fromArray(1,2,3,4,5);
Observable createObservable = Observable.create(emmit->emmit.onNext(1));
Observable justObservable = Observable.just(1);
先简单介绍下这几个Observable的作用,fromArray的作用是将数组中的元素作为onNext事件发送,create的作用是发送自定义事件,just的作用是发送单个事件。
上一小节有讲到实际的订阅行为是由各个Observable类中subscribeActual()方法实现的,我们来看下这三个类的subscribeActual()方法。
除去细枝末节,这三个方法都可以分成以下三步
1.创建被观察者对象,并传入观察者observer,建立两者的关联关系;
2.触发onSubscribe事件,观察者响应该事件;
3.进行事件的拉取,我们可以进入到d.run()
,source.subscribe(parent)
,sd.run()
这些方法的内部看一些,可以看到这些方法就是在发送onNext(),onError(),onComplete()
等事件。
下图是整个流程中的相关类图。实际事件的发送者是FromArrayDisposable等对象,而实际的观察者,则是一个实现了Observer接口的实体类。如果我们在subscribe时传入的是一个lambda表达式,之后会被包装成一个默认的LambdaObserver对象,进行事件消费。
包装
RxJava中提供了丰富的操作符,比如flatMap,concatMap等可以对事件转换,subscribeOn,observableOn等可以对生产和消费的线程进行控制。这些操作符实际上调用了Observable中的包装方法对原有的可观察对象进行包装,返回了一个增强了的可观察对象。
操作符种类繁多,在这就不一一举例,我们以flatMap为例,分析一下这些操作符是如何工作的。
首先,flatMap操作会返回一个ObservableFlatMap对象,在创建这个对象时,会将原始的Observable对象作为构造函数的参数传入。
查看其核心方法subscribeActual,
@Override
public void subscribeActual(Observer super U> t) {
if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)) {
return;
}
source.subscribe(new MergeObserver(t, mapper, delayErrors, maxConcurrency, bufferSize));
}
可以看到这一类对象的subscribeActual方法和上一节中的方法不太一样,这里面并没有去实际的创建观察关系,而是做了两件事:
1.对观察者进行增强,将其包装成为MergeObserver对象
2.再调用source的subscribe方法,这里source就是前面构造函数中传入的Observable对象,由其再进行观察关系的建立。
下图是RxJava中装饰器模式的相关类图:所有的包装类都继承了AbstractObservableWithUpstream类,该抽象类有一个类型为ObservableSource的成员函数,用来持有被装饰的对象。
Observable是支持链式操作的,就和Java 8中的Stream一样,我们来考虑这样一行代码。
Observable.fromArray(1,2,3,4,5).flatMap(num->Observable.just(num)).observeOn(Schedulers.newThread()).subscribe(num-> System.out.println(num));
我们在分析上面这串代码时,一定会凌乱非常,在看源码时也会看到前面忘掉后面,但是如果我们对RxJava的包装流程足够了解的话,就可以很轻松的对上述代码进行分析。
流程浅析
我们以一段常见的代码分析事件产生和消费的流程
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(@io.reactivex.annotations.NonNull ObservableEmitter emitter) throws Exception {
emitter.onNext(1);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onNext(@io.reactivex.annotations.NonNull Integer integer) {
System.out.println(integer);
}
@Override
public void onError(@io.reactivex.annotations.NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
在分析之前,我们先定义几个概念,source代表着被观察者;downStream代表着观察者;它们在下面的代码将会重复出现。
Observable.create(ObservableOnSubscribe source)
Observable.create(ObservableOnSubscribe source)
创建了一个ObservableCreate(ObservableOnSubscribe
对象,其内部持有了真实的被观察者ObservableOnSubscribe
,我们将这个ObservableOnSubscribe
称为原始被观察者,它是一个接口,内部定义了subscribe()方法:
public interface ObservableOnSubscribe {
/**
* Called for each Observer that subscribes.
* @param emitter the safe emitter instance, never null
* @throws Exception on error
*/
void subscribe(@NonNull ObservableEmitter emitter) throws Exception;
}
小结:
ObservableCreate
持有的source
为ObservableOnSubscribe
ObservableCreate.subscribeOn(Schedulers.IO)
接着我们调用了ObservableCreate对象的subscribeOn,并传入了IO线程调度器,subscribeOn()方法的实现在Observable类,ObservableCreate继承了Observable类
#Observable
public final Observable subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn(this, scheduler));
}
其实就是创建了ObservableSubscribeOn
对象,并传入了ObservableCreate对象和IO线程调度器。查看ObservableSubscribeOn
的构造函数:
public ObservableSubscribeOn(ObservableSource source, Scheduler scheduler) {
super(source);
this.scheduler = scheduler;
}
可以看到ObservableSubscribeOn
把source传给了父类,
ObservableSubscribeOn
继承了AbstractObservableWithUpstream
,因此AbstractObservableWithUpstream
持有了ObservableCreate
对象,但我们可以理解为ObservableSubscribeOn
持有了ObservableCreate
对象。
小结:
ObservableSubscribeOn
持有了source
为ObservableCreate
ObservableSubscribeOn.observerOn(AndroidSchedulers.mainThread())
observerOn()
方法的实现同样是在Observable
类中:
public final Observable observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn(this, scheduler, delayError, bufferSize));
}
可以看到也只是创建了一个ObservableObserveOn
对象,并传入了ObservableObserveOn
对象和主线程调度器,这里的delayError
和bufferSize
传入的是默认值,暂且不表,查看ObservableObserveOn
的构造函数:
public ObservableObserveOn(ObservableSource source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
这里同样的是把source传给了父类,ObservableObserveOn
同样也是继承了AbstractObservableWithUpstream
。
小结:
ObservableObserveOn
持有了source
为ObservableSubscribeOn
ObservableObserveOn.subscribe(observer)
接着我们调用了ObservableObserveOn对象的subscribe()方法,并传入了observer,该observer是最外层的Observer
public interface Observer {
void onSubscribe(@NonNull Disposable d);
void onNext(@NonNull T t);
void onError(@NonNull Throwable e);
void onComplete();
}
subscribe(observer)
方法的实现是在Observable类中,其内部调用了subscribeActual(observer)
,subscribeActual(observer)
是抽象方法,具体实现是在子类中,查看ObservableObserveOn
类的subscribeActual(observer)
:
# ObservableObserveOn
@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(observer, w, delayError, bufferSize));
}
}
1.创建一个任务,scheduler为AndroidSchedulers(主线程);
createWorker()
的实现是在HandlerScheduler
中,该方法创建了一个HandlerWorker
对象,它ji'c持有一个主线程关联的handler(new Handler(Looper.getMainLooper())
);
2.创建一个Observer观察者 => ObserveOnObserver
,持有一个传进来的observer和worker,传进来的observer是最开始最外面的Observer
ObserveOnObserver(Observer super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
this.downstream = actual;
this.worker = worker;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
3.为被观察者和观察者之间建立订阅关系
这里的
source
为ObservableSubscribeOn
小结:
ObserveOnObserver
持有了observer
为interface Observer
ObservableSubscribeOn.subscribe(observer)
接着查看ObservableSubscribeOn
的subscribeActual(observer)
方法,源码如下:
# ObservableSubscribeOn.java
@Override
public void subscribeActual(final Observer super T> observer) {
final SubscribeOnObserver parent = new SubscribeOnObserver(observer);
observer.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
1.创建一个Observer观察者 =>SubscribeOnObserver
SubscribeOnObserver
持有一个传进来的observer
,这个传进来的observer是我们上一步创建的ObserveOnObserver
对象
2.调用ObserveOnObserver.onSubscribe(parent)
查看源码:
# ObserveOnObserver.java
@Override
public void onSubscribe(Disposable d) {
// ...
downstream.onSubscribe(this);
}
}
这里的downstream下游即我们传进来的观察者observer,也就是
ObserveOnObserver
所持有的interface Observer
的实现了,也就是最外层的代码:
@Override
public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
System.out.println("onSubscribe");
}
-
scheduler.scheduleDirect(new SubscribeTask(parent))
其实就是执行线程,scheduler就是我们传进来的线程调度器Schedulers.IO,
SubscribeTask
实现了Runnable,查看它的run方法:
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver parent;
SubscribeTask(SubscribeOnObserver parent) {
this.parent = parent;
}
@Override
public void run() {
source.subscribe(parent);
}
}
它的run方法只有一句代码:
source.subscribe(parent);
parent是SubscribeOnObserver
对象,source是传递给ObservableSubscribeOn
的source,也就是最开始的ObservableCreate
对象。因此实际上是调用了ObservableCreate
的subscribe()
方法,并传入了SubscribeOnObserver
对象;
小结
SubscribeOnObserver
持有了observer
为ObserveOnObserver
onSubscribe
方法是最先执行的方法,并且它的线程和当前线程一样,因为此时还没有执行线程切换。
ObservableCreate.subscribeActual(observer)
方法是运行在子线程的。
ObservableCreate.subscribe(observer)
查看ObservableCreate
的subscribeActual
方法源码如下:
# ObservableCreate.java
@Override
protected void subscribeActual(Observer super T> observer) {
CreateEmitter parent = new CreateEmitter(observer);
observer.onSubscribe(parent);
source.subscribe(parent);
}
- 创建了一个事件发射器
CreateEmitter
,并传入了observer;
这里的
observer
是SubscribeOnObserver
对象
2.SubscribeOnObserver
的onSubscribe()
方法只是为了设置Dispoable的值,不影响流程;
3.为被观察者和观察者之间建立订阅关系
这里的
source
是ObservableOnSubscribe
这里开始执行,外层页面代码的subscribe部分,开始发射数据
@Override
public void subscribe(@io.reactivex.annotations.NonNull ObservableEmitter emitter) throws Exception {
emitter.onNext(1);
}
小结
emitter
发射器发送数据是在子线程。
CreateEmitter.onNext()
上一步的emitter是CreateEmitter
# CreateEmitter.java
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
observer.onNext(t);
}
}
这里的observer
是SubscribeOnObserver
,查看SubscribeOnObserver
的onNext()
# SubscribeOnObserver.java
final Observer super T> downstream;
SubscribeOnObserver(Observer super T> downstream) {
this.downstream = downstream;
this.upstream = new AtomicReference();
}
@Override
public void onNext(T t) {
downstream.onNext(t);
}
这里的downStream
在SubscribeOnObserver
的构造函数传进来,SubscribeOnObserver
是在ObservableSubscribeOn.subscribeActual
创建的,downStream
就是ObserveOnObserver
对象,查看ObserveOnObserver
的onNext:
#ObserveOnObserver.java
@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);
}
}
最终是调用了worker执行任务,ObserveOnObserver本身实现了Runnable,它的run()方法中调用了ObserveOnObserver
所持有的observer
的onNext
方法,ObservableObserveOn
所持有的正是最外层的Observer
接口实现类,因此最后执行了
@Override
public void onNext(@io.reactivex.annotations.NonNull Integer integer) {
System.out.println(integer);
}
小结
worker.schedule(this);
这里又切换了线程到主线程,worker正是之前AndroidThread创建的HandlerWorker
,其内部持有主线程关联的handler,因此最后的onNext是在主线程执行。
只需要理解,每次 observerOn 和 subscribeOn 的时候,内部都会创建一个新的 observable 和 observer。
新创建的 observable 会引用前面的 observable,就是代码中我们分析的 source 变量。
新创建的 observer 会引用前面的 observer,就是代码中我们分析的 observer 变量。
最后我们 subscribe 的时候,是调用的最后创建的 observable 的方法。而每个 observable 内部又调用了 source 的 subscribe 方法,这样就形成了一层一层往前传递的调用链。当调用到最前面的一个 observable 的时候,就是我们自己创建的 observable,在这里我们需要手动触发与该 observable 对应的 observer 对象的 onNext 方法。而 observer 的 onNext 方法的内部又调用了 downstream 的 onNext 方法,这样就形成了一层一层往后传递的调用链。