RxJava原理探索

  • RxJava用来干什么

    RxJava is a Java VM implementation of ReactiveX (Reactive Extensions): a library for composing asynchronous and event-based programs by using observable sequences.

    简单来说,RxJava就是用来处理回调的,使用观察者模式来传递调用回溯,究其根源也就是使用普通的接口回调方式,更奇妙的是,它还使用了装饰模式来封装一层层回调,通过源码,我们才能体会它优雅的链式调用背后真正的美。

  • 源码看原理

    拿一个链式调用的例子来梳理RxJava的原理:

    Flowable.range(0, 10).doOnNext(System.out::println).all(integer -> integer < 5).
            blockingSubscribe(success -> System.out.println("Success: " + success));
    

    range()、doOnNext()、all()三个方法都会产生一个Flowable的子类对象。

    来看看range方法:

    RxJava原理探索_第1张图片

    可以看到,count不能小于0且不能大于最大整数,并且针对没有元素、只有一个元素和不止一个元素三种情况分别返回三个不同的Flowable子类对象。empty()方法会返回一个FlowableEmpty(),just()会返回一个FlowableJust(),大于一个的会返回一个FlowableRange()。

    这里我们先随便以其中的FlowableRange为例来看,那接下来就是FlowableRange().doOnNext方法了:

    RxJava原理探索_第2张图片

    这个方法是父类Flowable里面的方法,实际上又走到了doOnEach方法里面:

    RxJava原理探索_第3张图片

    onNext就是我们外面传入的lambda形式表示的Consumer对象,后面的三个参数分别是出现错误时、完成时、终止时的处理接口,这里因为没用到先不说,只要知道是构造了空的实例就好。这些参数都不能是null,最后返回了一个FlowableDoOnEach对象,接下来就用这个对象调用all方法:

    RxJava原理探索_第4张图片

    参数Predicate(断言)是用来判定条件的,构造了一个含有这个条件的FlowableAllSingle对象。

    到这里,可以看出来这个链式调用就是一步步的把一开始的Flowable子类对象一步步封装的过程,方式就是通过每个装饰对象的构造方法和前后的Flowable类型实例联系在一起:

    RxJava原理探索_第5张图片

    new FlowableRange(0,10)把传入的start(这里是0)和count(这里是10)保存

    RxJava原理探索_第6张图片

    new FlowableDoOnEach(this,onNext)把FlowableRange对象和System.out::println(Consumer实例)保存

    RxJava原理探索_第7张图片

    new FlowableAllSingle(this,predicate)把FlowableDoOnEach对象和integer -> integer < 5(Predicate实例)保存

    最后调用的方法就是开启往回回溯调用,看一下最后的Single类里的blockingSubscribe方法(其实通常调用subscribe方法就可以,这里之所以用blockingSubscribe方法是因为它涵盖了subscribe方法,不同的是blockingSubscribe方法会多一个observer.blockingConsume的调用,可以看到blockingSubscribe的onSuccess参数交给了它,因为在前面的操作完成后才会调用,至于怎么做的后面会讲到):

    RxJava原理探索_第8张图片

    现在的重心到了subscribe方法里面:

    RxJava原理探索_第9张图片

    这里的observer经过了一层RxJavaPlugins.onSubscribe(this,observer)的操作,前面链式装饰的时候也看到过这个RxJavaPlugins,你可以把它看成是一个全局的配置类,我们前面的onAssembly方法:

    RxJava原理探索_第10张图片

    可以看到source会通过一个叫做onFlowableAssembly的对象处理一下再返回,这个onFlowableAssembly对象是一个静态的volatile(为了并发需要)变量:

    @Nullable
    static volatile Function<? super Flowable, ? extends Flowable> onFlowableAssembly;
    

    所以如果你通过onFlowableAssembly的set方法事先设置了,那么只要你的装饰对象是Flowable类型,构造的时候就会先调用这个对象处理一下。同样RxJavaPlugins.onSubscribe方法也一样,如果设置了则每次subscribe的时候都会先调用。

    回到主线,try块里会调用subscribeActual方法,这个方法是Single里的abstract方法,所以这里的调用其实是在子类调用的,那这里的子类也就是FlowableAllSingle,找到它里面的subscribeActual方法看一下:

    image-20200910175252130

    其中的observer就是前面的BlockingMultiObserver对象,source就是链式创建它的FlowableDoOnEach对象,调用subscribe方法同样会调用FlowableDoOnEach的subscribeActual方法,传入一个构造的AllSubscriber对象:

    image-20200911095547988

    observer交给了AllSubscriber,赋值给了downstream,注意这个词是下游的意思,结合链式调用,这个词很形象。

    FlowableDoOnEach的subscribeActual方法:

    RxJava原理探索_第11张图片

    也是一样的,只不过这里针对不同的Subscriber实例构造不一样的往上游传递的Subscriber,因为这里的AllSubscriber不是ConditionalSubscriber类型,所以会走else分支,向其上游FlowableRange的subscribeActual方法传递一个DoOnEachSubscriber对象,s就是AllSubscriber,onNext就是Consumer对象(这里是System.out::println):

    RxJava原理探索_第12张图片

    这里和上面不同,它没有source,所以这里就是向上游传递的终点,现在开始往下游传递,传递的对象是一个RangeSubscription,所以现在回到DoOnEachSubscriber的onSubscribe方法里,但是在DoOnEachSubscriber里没找到这个方法,于是我们在其父类BasicFuseableSubscriber里找到了它:

    RxJava原理探索_第13张图片

    首先检查工作SubscriptionHelper.validate()代码如下:

    RxJava原理探索_第14张图片

    这里就是要求当前操作的next不能为空,并且upstream要为空,若不为空说明之前还有未完成的操作,就把当前的next取消并在reportSubscriptionSet里面抛出"Subscription already set!"异常。upstream就是在这里赋值的,然后关键代码就是downstream.onSubscribe(this),这里的downstream是构造方法传进来的,所以也就是AllSubscriber,所以这里的onSubscribe方法就是AllSubscriber里面的:

    RxJava原理探索_第15张图片

    同样也是上面类似的操作,到了BlockingMultiObserver的onSubscribe()方法里:

    RxJava原理探索_第16张图片

    看起来这趟传递就是把一系列Subscription赋给相应的upstream关联起来,然后调用s.request方法开始沿着关联的upstream再往上回溯,那这趟回溯是做什么的呢,s也就是之前的BasicFuseableSubscriber,它的request调用了upstream的request方法,upstream也就是FlowableRange的subscribeActual里创建的RangeSubscription对象,在其父类BaseRangeSubscription里面找到了request方法:

    RxJava原理探索_第17张图片

    传递的n是Long.MAX_VALUE,SubscriptionHelper.validate(n)要求n不能小于0,如果是最大值Long.MAX_VALUE则使用fastPath否则使用slowPath,我们这里n是Long.MAX_VALUE,所以看一下fastPath():

    RxJava原理探索_第18张图片

    用一个for循环把index和end之间的整数依次传递给downstream的onNext,最后往下调用onComplete直到最后一个downstream的onComplete执行完成,在这个过程中调用onNext和onComplete之前都要判断订阅是否已经被取消了,若已取消则不继续操作了。onNext又怎么做的呢?这里的downstream显然是DoOnEachSubscriber:

    RxJava原理探索_第19张图片

    这里的sourceMode是NONE(0),所以会走try-catch,先调用onNext.accept,即System.out.println(t),然后继续调用它的下游downstream的onNext方法,也就是AllSubscriber:

    RxJava原理探索_第20张图片

    这里调用predicate.test(t)验证,即判断t<5?如果过程中发生了错误则链式通知上游依次取消并执行onError回调,如果条件满足则结束此次调用,再次回到fastPath中的for循环中执行下一次传递调用,如果不满足则结束for循环,注意如果拿这个例子来说,range(0,10)根据条件t<5会输出0,1,2,3,4,5,之所以会输出5是因为调用是根据链式调用顺序执行,所以会先执行println(5)再判断5满不满足继续循环。

    执行完成最终都会执行到最后的downstream的onSuccess中,不同的是,通过顺利执行完fastPath的onSuccess传递的是true,而因条件或者错误canceled的传递的是false,BlockingMultiObserver的onSuccess如下:

    RxJava原理探索_第21张图片

    其父类中countDown方法调用如下:

    public void countDown() {
           
        sync.releaseShared(1);
    }
    

    sync在构造的时候初始化的:

    public BlockingMultiObserver() {
           
        super(1);
    }
    

    RxJava原理探索_第22张图片

    sync.releaseShared(1)方法在Sync的父类AbstractQueuedSynchronizer中:

    RxJava原理探索_第23张图片

    tryReleaseShared是上面Sync重写的,主要就是取当前的state值,若是0则返回false表示没什么可释放的了,若不是0则判断减1后的值是否是0,不是的话也不执行release操作,总之就是state只能是0或1,而且释放前只能是1。看看doReleaseShared操作:

    RxJava原理探索_第24张图片

    其实这里会直接走到break,head是null,原因在于之前我们的链式调用和blockingSubscribe是在同一个线程中同步调用的,所以调用的blockingSubscribe中subscribe是在observer.blockingConsume之前调用的,而设置head的代码在blockingConsume中的await中的后续操作设置的:

    RxJava原理探索_第25张图片

    最后有错误则onError.accept,没有就onSuccess.accept,即success -> System.out.println("Success: " + success),此时success是false。最后的输出结果是:

    RxJava原理探索_第26张图片

你可能感兴趣的:(Rx系列,java,rxjava)