首先对rxjave简单的一个认知
描述:响应式编程,观察者设计模式,实现异步操作的库.
这个描述并不是很详细但是足够精简,接下来基于描述来分析Rxjava源码中是如何体现了这些特点。(主要为面试自我总结方便记忆)
代码1:
Observable
.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("1");
}
})
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.parseInt(s);
}
})
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
代码1是Rxjava最简单的一个使用,这样能方便我们分析。对代码进行简单分析:
Rxjava是一个观察者设计模式,那肯定离不开这个模式的套路,(主体成员 1.Observable 被观察者 2.Observer 观察者),
我们从代码的结构来看,1.通过Observable.create方法创建了一个被观察者,2.subscribe传入了一个观察者,这时候我们找到了两个主体。
订阅流程:
代码1中Observable在调用create方法后接着调用了map,看下map方法的实现。
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
很简单对传入的方法和this进行了一个封装,抛开其他细节,注意最后我们拿到了ObservableMap的对象。可以再去看下其他的一些操作符,发现大致如此这样先得出一个简单结论,
Observable在各个操作符下进行了一个分装,不同操作符分装成不同的Observablexxx的对象进行返回。
接着简单看下ObservableMap里面长什么样,
public final class ObservableMap<T, U> extends AbstractObservableWithUpstream<T, U> {
final Function<? super T, ? extends U> function;
public ObservableMap(ObservableSource<T> source, Function<? super T, ? extends U> function) {
super(source);
this.function = function;
}
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
....}
代码很简单,把传入的this(指Observable,因为是被观察者调用的map方法)取名source存下,把对应的function也保存下来,对照的看一下其他的操作符对应Observablexxx里面的实现就能发现也是大同小异的,这边结合之前再做一个简单的结论:
Observable在各个操作符下进行了一个分装,不同操作符分装成不同的Observablexxx的对象进行返回。Observablexxx中将持有了上一层级的对象,以及自身的处理操作。
这边其实就能明白了,Observable 被观察者 调用了多少个操作符就会在外面包装多少层类,最后调用了最外面那层Observablexxx的subscribe方法,传入了Observer观察者。
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
....
}
}
操作主要点1.传入了一个Observer观察者,2.调用了subscribeActual,如同名字意思实际的订阅发生了。
而在subscribeActual里的操作就上调用上一级的subscribe,但是这边传入的Observer是进行分装过的,传入是Observablexxx对应的
xxxObserver,这个观察者分装了下一级的观察者以及自身特有的操作,把这个新的观察者通过subscribe返回给了Observablexxx的上一级
的Observable,无限的套娃到最初的observable的subscribe里。
可以看到虽然有很多不同的的Observablexxx,但是对应的subscribe操作其实类似就是,而subscribeActual里的操作也都大同小异,
就是调用上一级的subscribe的,传入自己分装好的observer。
所以可以看到ObservableOnSubscribe里的收到ObservableEmitter其实就是rxjav基于我们传入的observer层层分装后的观察者。
触发流程:
在我们调用onNext就开始触发通知观察者发生了事件,这里调用的是订阅流程中层层分装后的observer,在ObservableEmitter里的
onNext可以看到代码很简单,主要就是调用了下一级的观察者的onNext,我们再看下MapObserver里也是如此,调用了下一级observer的onNext,
而主要区别在于传入的参数是map操作符传入的方法调用结果,再去看其他的操作符也都是类似的,做了一些各自操作符对应的处理后把结果传递下取。
最后传递到我们设置的Observer中的onNext方法里,拿到了我们想要的数据。
总结:在订阅的流程中把我们的观察者做了层层分装,交给到被观察者,然后被观察者把通知的信息给了分装后的观察者,而这个分装后的观察者
把通知信息处理了一下,做成了符合下一个观察者想要的东西传递了过去,这样形成了类似工程流水线的模式,把针对通知信息不同的操作进行了划分分装,
最后在末端我们拿到了想要的东西。这样一来后期添加操作或者去掉操作十分方便,流水线的模式把操作之间完全解耦,
操作之间互不关联,你只要给下一个操作想要的东西就不会出错。
线程切换:
实现线程切换常用的就是subscribeOn和observeOn,对于这两操作符的简单理解:
subscribeOn:切换操作符上面的线程 observeOn:切换操作符后面的线程
从结果来看这是没有错的,但是在交错使用比较复杂的情况下的时候,就会很闷逼不确定。
subscribeOn起效果是发生在订阅流程,根据之前的分析,订阅流程主要操作就是对Observer进行了分装然后调用上一层级Observable的subscribe。
抱着这个目的我们去看,其实发现里面逻辑就很简单了,在ObservableSubscribeOn里的subscribeActual方法里,对下一层传来的Observer进行里分装成
SubscribeOnObserver,这个操作很熟悉,然后接下按分析应该就是调用上一级的subscribe,但是这里没有而是再进行了一层封装成了SubscribeTask,
点开一看就能很熟悉的source.subscribe了,SubscribeTask继承自Runnable,而他的run方法里调用的就是source.subscribe。
scheduler.scheduleDirect这个方法就是把Runnable放入rxjave中对应的线程池进行运行,这样就切换了后续操作的线程环境。
observeOn起效果是发生在触发流程里,根据之前分析,触发流程主要操作是实现自身Observer的操作,并调用下一个Observer的onNext方法传递过去。
在ObservableObserveOn中分装这个ObserveOnObserver时候会把我们设置的线程Scheduler传入,并且ObserveOnObserver是继承Runnable,
在onNext方法里可以看到,其实就是用我们设置的线程去执行了this,然后可以在ObserveOnObserver中的run方法了看到了很熟悉的onNext方法。
这样后续的Observer操作都会切换到新的线程里了。
备注:切换线程具体实现:subscribeOn是线程池 observeOn是handle