RxJava2的操作符变化的原理其实很简单,先通过最简单的map操作符学习。
Example:
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(5);
emitter.onNext(4);
emitter.onComplete();
}
}).map(new Function() {
@Override
public String apply(Integer integer) throws Exception {
return integer+"...";
}
}).subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG,"onNext:"+s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG,"onComplete:");
}
});
结果:
D/MainActivity: onNext:5…
D/MainActivity: onNext:4…
D/MainActivity: onComplete:
通过例子可以看出:当使用map操作符时,emitter发射的数据会先被它变化(具体如何变化在apply方法中进行),变化之后的结果再传给观察者。
执行流程源码分析:
通过上一篇已经知道了RxJava2整体的执行流程,调用Observable.create方法会返回一个ObservableCreate对象,它持有ObservableOnSubscribe实例source。紧接着调用map方法进行变化
Observable#map
public final Observable map(Function super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap(this, mapper));
}
点进去会发现其实map方法是Observable中的方法,它又创建并返回了一个ObservableMap对象,这个对象持有了上游的ObservableCreate对象和一个用于变化的Function实例mapper。这个mapper就是map方法传进来的匿名对象。
.map(new Function() {
@Override
public String apply(Integer integer) throws Exception {
return integer+"...";
}
})
ObservableMap对象是重点,看看它是如何创建的?
public ObservableMap(ObservableSource source, Function super T, ? extends U> function) {
super(source);
this.function = function;
}
很简单,ObservableMap持有了上游的ObservableCreate对象作为它的source,以及用于变化的function对象。
紧接着调用ObservableMap的subscribe方法并把观察者传进去,观察ObservableMap的继承结构可以发现它间接继承了Observable,因此subscribe方法最终会调用到ObservableMap的subscribeActual方法。
ObservableMap#subscribeActual
@Override
public void subscribeActual(Observer super U> t) {
source.subscribe(new MapObserver(t, function));
}
这里调用source.subscribe方法其实就是调用它持有的ObservableCreate对象的subscribe方法,然后ObservableCreate的subscribe方法会调用到ObservableCreate的subscribeActual,接着会调用到ObservableCreate持有的ObservableOnSubscribe实例subscribe方法。
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(5);
emitter.onNext(4);
emitter.onComplete();
}
})
可以看到经过不停的调用上游的方法,MapObserver对象最终会被传递并封装到emitter中,然后调用emitter对象的一系列onNext方法、onComplete方法其实都是调用MapObserver中对应的onNext、onComplete方法。现在再来分下MapObserver对象。
在上面创建MapObserver对象时给他传递了观察者Observer对象和用于变化的Function对象。
MapObserver(Observer super U> actual, Function super T, ? extends U> mapper) {
super(actual);
this.mapper = mapper;
}
因此变化和发射数据的一定都是通过它完成的。这里只看MapObserver的onNext方法。
MapObserver#onNext
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
U v;
try {
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");//1
} catch (Throwable ex) {
fail(ex);
return;
}
downstream.onNext(v);//2
}
主要看注释1、2处代码,在注释1处调用mapper.apply(t)对要发射的数据进行变化,变化的结果就是v,然后再注释2处调用下游的观察者对象的onNext方法将变化的结果发送出去。这样map操作符的整体变化流程就分析完了。
总结:在通过subscribe订阅观察者时会把观察者对象和用于变化的Function对象封装到MapObserver中,然后经过流转会把MapObserver对象封装到emitter发射器中,这样当调用emitter发射器发射我们的数据时内部就会调用MapObserver中对应的方法,MapObserver又持有了用于变化的Function对象和下游观察者,因此在它发射数据时内部会先调用Function对象对象对数据进行变化,再将变化后的数据传给下游观察者。
compose操作符通常是用来消除重复代码的,比如我们在进行注册时可能经过切换线程、对结果进行变换,极端情况下还有可能做多次变化,然后再登陆逻辑同样还要进行切换线程、对结果进行变换。这部分的代码大致都是重复的,通过compose操作符我们可以对重复代码进行复用。
Example:
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext("正在通过网络获取数据...");
emitter.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function() {
@Override
public String apply(String integer) throws Exception {
return "结果";
}
})
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG,"onNext:"+s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG,"onComplete:");
}
});
上面这个例子可能很常见,在子线程中访问网络,获取到数据进行变化,然后在主线程显示出来。切换线程和数据变化这部分代码可能在多组类似的过程中都会遇到,因此可以通过compose操作符对这些应用一系列相同操作符的过程来复用相同的操作。
首先:创建一个ObservableTransformer实例,需要复用的操作可以放在这个对象的apply方法中。
private ObservableTransformer observableTransformer=new ObservableTransformer(){
@Override
public ObservableSource apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function() {
@Override
public String apply(String integer) throws Exception {
return "结果";
}
});
}
};
以后再有相同的操作时我们就不用写切换线程、变化结果这几行代码了。
然后通过compose操作符使用observableTransformer。
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext("正在通过网络获取数据...");
emitter.onComplete();
}
}).compose(observableTransformer) //1
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Log.d(TAG,"onNext:"+s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG,"onComplete:");
}
});
可以看到在注释1 运用了使用了compose操作符,最终的效果和开始的例子是一样的。
compose操作符原理分析:
compose操作符是对Observable进行变化的,它接收上游的Observable返回新的Observable对象。
当调用ObservableCreate的compose方法实际上就是调用Observable的compose方法
//Observable#compose
public final Observable compose(ObservableTransformer super T, ? extends R> composer) {
return wrap(((ObservableTransformer) ObjectHelper.requireNonNull(composer, "composer is null")).apply(this));
}
在这个方法中就是调用了wrap方法,而wrap方法入参部分调用了composer对象的apply方法,然后将ObservableCreate传进去。
private ObservableTransformer observableTransformer=new ObservableTransformer(){
@Override
public ObservableSource apply(Observable upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(new Function() {
@Override
public String apply(String integer) throws Exception {
return "结果";
}
});
}
};
可以看到apply方法接收上游的Observable然后返回新的ObservableSource(Observable 实现了ObservableSource)。因此wrap方法接受的其实就是这个新的ObservableSource对象。
//Observable#wrap
public static Observable wrap(ObservableSource source) {
ObjectHelper.requireNonNull(source, "source is null");
if (source instanceof Observable) {
return RxJavaPlugins.onAssembly((Observable)source);//1
}
return RxJavaPlugins.onAssembly(new ObservableFromUnsafeSource(source));
}
在wrap方法中将source转为Observable类型的然后就直接返回了,可以看到其实compose操作符的原理也很简单。
操作符的分析暂时告一段落了,对于其他的操作符原理其实都是大同小异。