阅读 2713

RxJava源码浅析———订阅流程、map与Filter操作符实现原理

RxJava源码浅析———订阅流程、map与Filter操作符实现原理

RxJava是一个非常流行的基于观察者模式的响应式编程框架,在Android开发等领域有很广泛的应用。作为Android开发者,我们有必要了解一下RxJava的实现原理,掌握RxJava的设计思想,这样我们才能更加熟练的使用RxJava来编写优秀的代码。

订阅流程

要使用RxJava,首先要创建一个被观察者Observable对象。我们通常是使用Observable的create方法来创建一个Observable对象的,如下:

    Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            e.onNext(new Integer(1));
            e.onNext(new Integer(2));
            e.onComplete();
        }
    });    
复制代码

我们来看一下create方法的源码:

    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }
复制代码

在create方法中,首先对被传入的参数ObservableOnSubscribe对象进行了空检查,然后new了一个ObservableCreate对象,并将这个对象作为参数传入了RxJavaPlugins.onAssembly方法中,我们首先来看onAssembly方法的源码:

    public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
        Function<? super Observable, ? extends Observable> f = onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
    }
复制代码

在onAssembly方法中首先判断onObservableAssembly对象是否为null,如果不为null则调用apply方法并返回结果,如果为null则直接返回传入的参数。在默认情况下onObservableAssembly为null,也就是说默认情况下onAssembly方法其实什么都没有做,直接将传入的Observable对象返回了。

回到Observable的create方法,我们再来看new ObservableCreate到底做了什么,ObservableCreate类的构造方法如下:

    public final class ObservableCreate<T> extends Observable<T> {
        final ObservableOnSubscribe<T> source;
    
        public ObservableCreate(ObservableOnSubscribe<T> source) {
            this.source = source;
        }
        
        ...
    }    
复制代码

ObservableCreate类的构造方法很简单,直接将传入的ObservableOnSubscribe对象保存在了自己的一个全局变量source中,并且这个变量被final所修饰。而我们通过分析ObservableCreate类可以发现,ObservableCreate继承自Observable,也就是说ObservableCreate本身也是一个被观察者对象。

通过上面的分析我们可以看出,Observable.create方法其实就是创建了一个ObservableCreate对象,并把一个ObservableOnSubscribe保存在了这个ObservableCreate中。

创建完Observable,我们便可以调用它的subscribe方法来关联相应的观察者:

    observable.subscribe(new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {
            Log.e("RxJava", "onSubscribe");
        }
    
        @Override
        public void onNext(Integer integer) {
            Log.e("RxJava", "onSubscribe" + integer.toString());
        }
    
        @Override
        public void onError(Throwable e) {
            Log.e("RxJava", "onError");
        }
    
        @Override
        public void onComplete() {
            Log.e("RxJava", "onComplete");
        }
    });
复制代码

我们来看一下subscribe方法的源码:

    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, 
                observer);//同上面的RxJavaPlugins.onAssembly方法,默认情况下直接将observer返回
    
            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
    
            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
         ...
        }
    }
复制代码

subscribe方法中先检查了observer对象是否为null,然后调用了RxJavaPlugins.onSubscribe方法,该方法默认情况下什么都不做直接将observer对象返回,然后又调用了subscribeActual方法。上面我们分析过,create方法生成的Observable其实是一个ObservableCreate对象,因此我们看一下ObservableCreate类中的subscribeActual方法:

    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);
    
        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }
复制代码

可以看到在subscribeActual方法中先生成了一个Emitter事件发射器,然后直接调用了observer的onSubscribe方法,因此onSubscribe方法才可以在事件发射之前被执行。然后又调用了source.subscribe方法,前面我们说过,这个source对象就是在create方法调用时传入的ObservableOnSubscribe对象,此时ObservableOnSubscribe的subscribe方法就被调用了,各种事件也被成功的发射出去了。并且通过源码可以看出,如果在调用subscribe方法时出现异常,则会直接让Emitter发射一个onError事件。

至此一个最简单的订阅流程就完成了。

事件的发射

上面我们简单的分析了Rxjava的订阅流程,可见事件最终是在subscribeActual方法中调用source.subscribe(parent)来发射的。我们在subscribeActual方法中生成了一个CreateEmitter对象,并将这个Emmitter传入了onSubscribe方法中。通过本文最开始的那个例子可以看出,各种事件其实是由这个Emmitter来发射的,我们首先看一下CreateEmmitter对象的构造方法:

    CreateEmitter(Observer<? super T> observer) {
        this.observer = observer;
    }
复制代码

可见在CreateEmmitter中持有了Observer对象。我们可以通过CreateEmmitter的onNext、onComplete和onError方法来发射各种事件,在这里以onNext的源码为例看一下Emmitter究竟是如何将事件发送给Observer的:

    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;
        }
        if (!isDisposed()) {
            observer.onNext(t);
        }
    }
复制代码

CreateEmmitter的onNext方法非常简单,就是直接调用了observer.onNext方法,onComplete和onError的原理也和onNext方法大同小异,只不过在onComplete和onError方法中还会调用dispose()方法,这样在调用onComplete和onError方法之后observer就无法在接收任何事件了。

map操作

我们可以通过map操作来进行数据类型的转换,map的基本使用方法如下:

    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            e.onNext(new Integer(0));
            e.onComplete();
        }
    }).map(new Function<Integer, String>() {
        @Override
        public String apply(Integer integer) throws Exception {
            return integer.toString();
        }
    }).subscribe(new Observer<String>() {
        public void onSubscribe(Disposable d) { Log.e("RxJava", "onSubscribe");}
        public void onNext(String s) { Log.e("RxJava", "onNext" + s);}
        public void onError(Throwable e) {Log.e("RxJava", "onSubscribe");}
        public void onComplete() {Log.e("RxJava", "onSubscribe");}
    });
复制代码

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));
    }
复制代码

可以看出map方法其实和create方法很像,只不过这里返回的是一个ObservableMap对象,并将原来的Observable对象和参数mapper传入了ObservableMap的构造方法。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);//父类构造方法将source保存在了一个成员变量中
            this.function = function;
        }
        
        ...
    }    
复制代码

ObsevableMap的构造方法也只是将原Observable对象和Function对象分别保存在了ObservableMap对象的成员变量source和function中。

由此可见,map方法实际上就是生成了一个ObservableMap对象,并将原来的Observable和参数Function保存在了这个ObservableMap对象中。这个时候我们通过subscribe方法进行订阅时,实际上是调用的ObservableMap对象的subscribe方法。之前我们分析过,subscribe方法内部又调用了subscribeActual方法,ObservableMap的subscribeActual方法如下:

    public void subscribeActual(Observer<? super U> t) {
        source.subscribe(new MapObserver<T, U>(t, function));
    }
复制代码

可见subscribeActual方法中调用的还是是原Observable的subscribe方法,只不过subscribe方法中的参数不再是我们最初生成的那个Observer对象,而是对Observer进行了转换,变成了一个MapObserver对象。当各种事件发出后,接收事件的就变成了这个MapObserver对象,MapObserver对象对onNext方法进行了重写,MapObserver的源码如下:

    static final class MapObserver<T, U> extends BasicFuseableObserver<T, U> {
        final Function<? super T, ? extends U> mapper;
    
        MapObserver(Observer<? super U> actual, Function<? super T, ? extends U> mapper) {
            super(actual);
            this.mapper = mapper;
        }
    
        @Override
        public void onNext(T t) {
            ...
            U v;
    
            try {
                v = ObjectHelper.requireNonNull(mapper.apply(t), 
                    "The mapper function returned a null value.");
            } catch (Throwable ex) {
                fail(ex);
                return;
            }
            actual.onNext(v);
        }
    
        ...
    }
复制代码

在onNext方法中,传入的参数T是原数据类型,U是转换后的数据类型,之后又调用了mapper.apply(t)来实现了数据类型的转换,这个mapper即我们在调用map方法时传入的Function对象。最后又直接调用了原Observer的onNext方法,并传入了转换后的数据类型,最终完成了map过程。

filter操作

我们也可以通过filter方法来对发射的事件进行过滤,filter方法的基本使用如下:

    Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            e.onNext(new Integer(0));
            e.onComplete();
        }
    }).filter(new Predicate<Integer>() {
        @Override
        public boolean test(Integer s) throws Exception {
            return integer.intValue() > 0 ? true : false;
        }
    }).subscribe(observer);
复制代码

看一下filter方法的源码:

    public final Observable<T> filter(Predicate<? super T> predicate) {
        ObjectHelper.requireNonNull(predicate, "predicate is null");
        return RxJavaPlugins.onAssembly(new ObservableFilter<T>(this, predicate));
    }
复制代码

可以看到filter方法的源码和create方法、map方法非常相似,只不过这次的返回数据有变成了ObservableFilter。可见filter方法和create、map方法的套路基本一致,那我们直接来看ObservableFilter的subscribeActual方法:

    public void subscribeActual(Observer<? super T> s) {
        source.subscribe(new FilterObserver<T>(s, predicate));
    }
复制代码

与ObservableMap类的subscribeActual方法类似,ObservableFilter类的subscribeActual方法也是直接调用了原Observer的subscribe方法,并传入了一个FilterObserver对象,参照之前分析map操作时的套路,我们直接看FilterObserver对象的onNext方法:

    public void onNext(T t) {
        if (sourceMode == NONE) {
            boolean b;
            try {
                b = filter.test(t);
            } catch (Throwable e) {
                fail(e);
                return;
            }
            if (b) {
                actual.onNext(t);
            }
        } else {
            actual.onNext(null);
        }
    }
复制代码

FilterObserver的onNext方法很简单,直接调用filter.test方法,如果返回true,就调用actual.onNext方法,否则什么都不做。这样就实现了事件的过滤。

通过分析RxJava的订阅流程与map、filter操作符的源码,我们可以对RxJava的核心思想有一个大致的了解,RxJava中的很多其他操作都与map、filter类似,只要掌握了核心思想便不难理解。本文只是对RxJava的原理进行一个简单的讲解,因本人能力有限,如果读者发现文中有什么错误或不足之处,希望能帮忙指出,大家一起共同进步。

文章分类
Android
文章标签