上一篇文章中我们详细介绍了RxJava的一些常见的使用方法,只是很简单的基础使用,这边文章中我们一起来学习下RxJava更高深的使用方法。
什么是操作符?
操作符是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件。RxJava提供了很多很有用的操作符。
map()操作符就是用于变换Observable对象的,map操作符返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。
可能这样解释大家还不是很容易理解,下面举个例子,大家就明白了。
怎么使用?
比如我们现在有一个需求,有一个String数组,我们利用RxJava遍历的时候,我们要对数组中每个元素都转成Integer类型,这时候我们的map操作符就很有用了。
String[] nums = new String[]{"1", "2", "3"};
Subscriber subscriber = new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.e(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError");
}
@Override
public void onNext(Integer integer) {
Log.e(TAG, "onNext , integer = " + integer);
}
};
Observable.from(nums).map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return Integer.parseInt(s);
}
}).subscribe(subscriber);
logcat如下:
06-08 14:44:40.103 6775-6775/com.example.boguang.demo E/RxAndroidActivity: onNext , integer = 1
06-08 14:44:40.103 6775-6775/com.example.boguang.demo E/RxAndroidActivity: onNext , integer = 2
06-08 14:44:40.103 6775-6775/com.example.boguang.demo E/RxAndroidActivity: onNext , integer = 3
06-08 14:44:40.103 6775-6775/com.example.boguang.demo E/RxAndroidActivity: onCompleted
分析下上面的代码:
- 当我们调用
Observable.from(nums)
的时候,这时候返回给我们的其实是Observable<String>
类型 - 当我们调用map方法的时候,这时候返回给我们的就是
Observable<Integer>
类型了,也就是RxJava在map操作内部偷偷的给我们变换了类型,可谓是偷龙转凤
那map操作的原理是什么呢?
源码解析
既然map操作符这么神奇,那我们就从源码的角度看看他是怎么做到的。map内部代码:
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return unsafeCreate(new OnSubscribeMap<T, R>(this, func));
}
unsafeCreate方法代码:
public static <T> Observable<T> unsafeCreate(OnSubscribe<T> f) {
return new Observable<T>(RxJavaHooks.onCreate(f));
}
从上面代码可见,map方法就一行代码,就是创建了Observable
对象,关键在实例化了OnSubscribeMap
,实例化OnSubscribeMap
需要两个参数,一个是当前对象,也就是我们上面说的第一步的 Observable<String>
,第二个参数就是我们传进来的func。
在OnSubscribeMap
内部做了什么事情呢?
其实OnSubscribeMap
是继承自OnSubscribe
,所以当遍历的时候就会先执行到OnSubscribeMap
的call方法,call方法代码如下:
MapSubscriber<T, R> parent = new MapSubscriber<T, R>(o, transformer);
o.add(parent);
source.unsafeSubscribe(parent);
上面代码的source其实就是我们Observable<String>
,也就是from操作返回Observable,transformer也就是map传递的参数Func1,这里MapSubscriber
对Func1进行了包装,MapSubscriber
其实是一个Subscriber
,所以当调用onNext方法的时候,其实先会调用MapSubscriber
的onNext,同理,onError和onComplete,接下来看看MapSubscriber
的onNext内部实现:
先列出其构造方法:
public MapSubscriber(Subscriber<? super R> actual, Func1<? super T, ? extends R> mapper) {
this.actual = actual;
this.mapper = mapper;
}
上面的actual其实就是我们在上面例子中subscribe方法传递的subscriber对象,mapper也就是我们map方法中参数Func1。
@Override
public void onNext(T t) {
R result;
try {
result = mapper.call(t);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
unsubscribe();
onError(OnErrorThrowable.addValueAsLastCause(ex, t));
return;
}
actual.onNext(result);
}
当订阅者收到onNext事件的时候,我们首先会调用到MapSubscriber
中的onNext方法,也就是上面那一段代码,在这段代码内部,首先调用了,result = mapper.call(t)
,然后把map方法内部处理后的结果传递到subscriber的onNext方法 actual.onNext(result)
,也就这样整个流程就完成了。
通过上面的分析,应该很清楚的说明了map操作的原理。map操作符其实就是对订阅者进行包装,有点类似拦截操作的意思,其实就是装饰者设计模式。