上一篇文章中我们详细介绍了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

分析下上面的代码:

  1. 当我们调用 Observable.from(nums) 的时候,这时候返回给我们的其实是 Observable<String> 类型
  2. 当我们调用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操作符其实就是对订阅者进行包装,有点类似拦截操作的意思,其实就是装饰者设计模式。