RxJava已经是日常开发必备的技能,连带面试也是常问的知识点,如果你还停留在是用的层次是远远不够的(因为还不够流弊),基本上现在出去面试,一般都是问一下你都用了什么技术,知不知道它的实现原理(心中犹如万马奔腾,头发都快掉光了,还天天源码源码。。。)?但是没办法,为了生活,为了提升自己的档次(方便吹),也要继续学习,我爱工作!我爱学习!
废话说了不说,先介绍一下大概的内容,本系列主要是涉及RxJava是如何实现函数式编程的,主要知识点:
(1)订阅是如何实现的?观察者模式
(2)多个操作符一起使用,它是如何连接起来的呢?装饰者模式
现在先从观察者模式开始介绍,然后步步深入。
订阅?观察者模式
在所有的设计模式当中,观察者模式算是在日常当中比较经常使用的了(有时候你使用了,可能你不知道)。我们先从它的定义开始:
土话:甲方(观察者)对乙方(被观察者)高度关注,一旦乙方状态发生变化,甲方马上就能收到反馈。之前看过一个现实版本的比喻,警察(观察者)抓小偷(被观察者),自己领悟。。。
现在来一段基础的RxJava使用代码,我们一起看一下:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
}
}).subscribe(new Observer<Integer>() {
@Override
...
@Override
public void onNext(Integer integer) {
//这里接收到的integer就是1
}
...
});
有没有发现有点意思?我Observer订阅你Observable,Observable发送了一个1,我Observer就收到了一个1,是不是就是一种观察者模式的应用?
好啦,如果懂什么是观察者模式的,上面这一段可以忽略。
操作符的使用及装饰者模式
一样,先介绍一下装饰者模式的定义:
土话:当觉得一个类的功能不够流弊的时候,我们需要给他扩展能力,有几种方式
(1)子类继承重写
(2)实现新接口
(3)我和目标对象实现相同的目标接口,然后在相应方法里面除了调用目标的,还加上了自己的(装饰者模式的使用)
…
所以简单来说就是为对象动态扩展功能。
举个例子:这两年线上的培训课(特点:学员可以根据自己的时间来安排学习时间–>动态)发展的是如火如荼,假设小明现在是一个基础Android开发工程师,作为祖国未来花朵,他积极向上,勤奋刻苦,在工作之余报了一个Android高级培训班,在培训之前,小明只会写一些基础代码,耦合高,自己都不忍直视。培训之后,他学会了设计模式,会搭建一些简单框架,于是他重构了一下自己的代码,耦合低了,心情也愉快了。这个培训的过程就是一个装饰小明(动态增强其能力)的过程。
现在我们使用RxJava编写一个简单的案例来分析其流程和装饰者模式的使用:
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
}
})
//新增
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return String.valueOf(integer);
}
})
.subscribe(new Observer<String>() {
...
@Override
public void onNext(String result) {
//收到的值类型发生变化
}
...
});
在这里我们不禁会感到疑问,最开始是一个Observable对象被Observer观察,现在怎么多了个map,Observer还是可以观察到呢,只不过是数据类型改变了?我们开始深入敌营:
//Observable
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
//辅助类,检查对象是否为空
ObjectHelper.requireNonNull(source, "source is null");
//默认返回ObservableCreate对象(hook功能默认没有开启)
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
从上面可以看出其实就是返回了一个ObservableCreate对象,而我们传入的ObservableOnSubscribe对象被ObservableCreate保存为成员变量。接下来继续看map
操作符:
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
//空检查
ObjectHelper.requireNonNull(mapper, "mapper is null");
//传入Observable和Function对象,返回ObservableMap对象(hook功能默认没有开启)
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
在ObservableMap的构造里面依然只是保存了这两个成员变量,这里将ObservableCreate包装成了ObservableMap对象,下面就是subscribe
了:
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
//空检查
ObjectHelper.requireNonNull(observer, "observer is null");
...
//默认无hook功能,直接返回observer
observer = RxJavaPlugins.onSubscribe(this, observer);
//空检查
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
//真正订阅逻辑函数
subscribeActual(observer);
...
}
//抽象方法,参数为观察者对象
protected abstract void subscribeActual(Observer<? super T> observer);
好了,从上面我们可以发现,我现在已经具备了一个Observer对象,然后调用了subscribeActual函数,subscribeActual函数是抽象的由子类实现,当前的子类是ObservableMap,因为刚刚经由map转化,它把原来的包装了一下,我们看一下它的实现,注意啦注意啦,要开车啦:
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
我们发现,ObservableMap的subscribeActual直接调用了source
的subscribe
函数,现在由两个问题,第一是source是什么?答案就是我们在上一步(这里是第一步)传入的ObservableCreate对象,就是说这里调用了ObservableCreate
的subscribe
函数。第二参数是什么呢,参数是MapObserver,它把我们原来的Observer对象t包装成MapObserver对象,我们现在去看看ObservableCreate的subscribe,发现它并没有实现,而是复用了父类Observable的subscribe,就是我们上面看到的那一段代码,所以直接看ObservableCreate
的subscribeActual
函数即可:
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函数。这里是MapObserver
observer.onSubscribe(parent);
try {
//回调订阅,此处为ObservableCreate订阅ObservableOnSubscribe
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
我们先看一下MapObserver的onSubscribe,它自己并没有实现,而是由父类BasicFuseableObserver
实现:
@SuppressWarnings("unchecked")
@Override
public final void onSubscribe(Disposable s) {
//期待当前Disposable对象为null,新值s不为null,返回true,否则返回false
if (DisposableHelper.validate(this.s, s)) {
//为当前Disposable对象赋值
this.s = s;
if (s instanceof QueueDisposable) {
this.qs = (QueueDisposable<T>)s;
}
//没有重写默认为true(控制是否继续访问onSubscribe函数)
if (beforeDownstream()) {
//actual是下游的Observer对象。
//此处为我们在subscribe中实现的Observer的匿名对象(即这里回调了我们实现的Observer的onSubscribe函数)
actual.onSubscribe(this);
//调用onSubscribe之后的操作,默认为空实现
afterDownstream();
}
}
}
我们继续看下面的代码ObservableOnSubscribe
对象调用subscribe
函数,就是我们示例代码中重写的subscribe函数,我们回过头去看一下:
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
}
到这里一整个流程就通了,我们从头开始理一下。
不知道这个流程图看不看得懂(美术小学没毕业,望见谅!!!),大致流程是这样的:
(1)通过Observable.create
创建了一个ObservableCreate
对象,这个对象保存了我们实现的匿名实现类ObservableOnSubscribe
。
(2)通过map
,创建了一个ObservableMap
对象,这个对象保存了(1)中的ObservableCreate
对象。
(3)通过subscribe
,实现了ObservableMap
对Observer
的订阅(不要奇怪是不是反了,这样是为了连续性)。
(4)在ObservableMap
实现了对Observer
的订阅时,内部会调用保存的ObservableCreate
对象对MapObserver
对象进行订阅(构造MapObserver对象,会将Observer保存在MapObserver的成员变量actual中)
(5)在ObservableCreate
对象实现了对MapObserver
的订阅时,ObservableCreate
保存的ObservableOnSubscribe
对象会对CreateEmitter
对象进行了订阅(构造CreateEmitter对象时,保存了MapObserver)
完成了从上游到下游,再从下游到上游的流程之后,我们开始分析事件,它是什么时候开始发射,又都发射了一些什么事件?我们从最上游的ObservableOnSubscribe
的subscribe
函数开始:
new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
}
}
什么鬼?这不就是我们示例代码里面写的嘛?要不然你以为呢。。。这里有两个地方要关注,分别是emitter
参数和它调用的事件。这个emitter参数看着有点熟悉,当然,因为上面从下游到上游的最后一步我们提到了一个CreateEmitter,它就是ObservableEmitter的自实现类。所以说这个emitter就是在上面我们订阅传递过来的CreateEmitter对象。
这里我们通过EmitterCreate发射了一个onNext事件,我们看一下流程,从EmitterCreate的onNext函数开始:
@Override
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;
}
//是否断开连接,没有断开则继续调用下游传递过来的Observer对象的onNext函数
if (!isDisposed()) {
observer.onNext(t);
}
}
很明显这里的主要逻辑在observer.onNext(t);
,这个observer对象在上面我们提高过,就是MapObserver对象,我们继续看:
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
actual.onNext(null);
return;
}
U v;
try {
//确认通过mapper.apply转化的结果不为空
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
//回调actual的onNext
actual.onNext(v);
}
MapObserver的onNext中有两个地方要关注:
(1)ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
关注这个干什么,不就是校验不为空,返回原值吗?对的,你说得对,不过注意这里调用了一个apply
函数,在这里正好就实现了我们示例代码中发射出来的值由Integer到String的装换。
new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
//将Integer -> 转换为String
return String.valueOf(integer);
}
}
这样的设计真的是太精妙了(请原谅我这个渣渣的偶像情节)。
(2) actual.onNext(v);
这里的actual就是我们刚才所说的Observer对象,即我们自己实现的观察者对象,这样我们发射的Integer
类型的1,到这里就变成了String
类型的1了。
到这里整个流程从订阅到事件的发射接收就都完成了。可能有人会问说好的装饰者呢?其实在上面的分析已经说明了,主要是两个特点:
(1)层层包装。例如把ObservableCreate
包装成ObservableMap
,把Observer
包装成MapObserver
等。
(2)在包装的同时扩展其功能。比如从ObservableCreate
到ObserverMap
,ObserverMap即保存了原有引用后面使用,还扩展了转化的功能(构造保存Function对象),在事件发射回调下游的Observer时,调用了Function
对象mapper
的apply
函数。
其实之前看别人文章也有说使用适配器模式的,从不同的角度看待问题可能结果会有所偏差,设计模式博大精深,重在思想,个人可能会比较偏向装饰者吧,大牛若是有不同意见,请轻虐o(╥﹏╥)o