RxJava 2.x 教程及源码揭秘(四)由设计模式,揭秘Rxjava流程原理

前言

     那么本文就将对Rxjava做一次详细的探索,相信跟随着博主的思路带着自己的思考,你一定也能掌握使用这个热门技术的要领。不仅如此,我们更要深入了解其内部原理,做到知其然,并且知其所以然。

    关于Rxjava的基本了解以及其使用,我在该系列的另一篇文章中已经介绍过了。详情关注

    RxJava 2.x 教程及源码揭秘(一)入门理解及应用

   在另一篇文章中,从源码出发,了解了其内部流程,理解Rxjava是如何实现线程的切换以及对任务逻辑的一些加工,并保持其链式结构

RxJava 2.x 教程及源码揭秘(三)Rxjava操作符源码解析

本文将从设计模式的角度,带你完整地回顾一下RxJava整个流程中一些重要的点,让你彻底了解这个流行的工具库的内部原理

 

RxJava涉及的设计模式

  1. 观察者模式           

    采用注册(Register)或者称为订阅(Subscribe)的方式,告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。举个安卓中最典型的例子吧,我们空间的点击事件监听就是一种观察者模式,对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的 OnClickListener 。

    采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。

    我们来对比下OnclickListener和RxJava

    OnClickListener 观察者模式

    通用观察者模式

    Buton持有OnClickListener的引用,当Button触发了点击事件,调用OnClickListene的OnClik方法,这就是观察者的流程,相信集合上面图片的对比,你已经知道了RxJava中各部分分别对应的角色。

    RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。ObservableObserver 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer

    1. 装饰者模式   

      RxJava所有操作符的共同原理:lift()

      这些变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。首先看一下 lift() 的内部实现(仅核心代码):

      // 注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
      // 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
      public  Observable lift(Operator operator) {
          return Observable.create(new OnSubscribe() {
              @Override
              public void call(Subscriber subscriber) {
                  Subscriber newSubscriber = operator.call(subscriber);
                  newSubscriber.onStart();
                  onSubscribe.call(newSubscriber);
              }
          });
      }

      这段代码很有意思:它生成了一个新的 Observable 并返回,而且创建新 Observable 所用的参数 OnSubscribe 的回调方法 call() 中的实现竟然看起来和前面讲过的 Observable.subscribe() 一样!然而它们并不一样哟~不一样的地方关键就在于第二行 onSubscribe.call(subscriber) 中的 onSubscribe 所指代的对象不同(高能预警:接下来的几句话可能会导致身体的严重不适)——subscribe() 中这句话的 onSubscribe 指的是 Observable 中的 onSubscribe 对象,这个没有问题,但是 lift() 之后的情况就复杂了点。当含有 lift() 时:                                                                    1.lift() 创建了一个 Observable 后,加上之前的原始 Observable,已经有两个 Observable 了;

    2. 2.而同样地,新 Observable 里的新 OnSubscribe 加上之前的原始 Observable 中的原始 OnSubscribe,也就有了两个 OnSubscribe

    3. 3.当用户调用经过 lift() 后的 Observablesubscribe() 的时候,使用的是 lift() 所返回的新的 Observable ,于是它所触发的 onSubscribe.call(subscriber),也是用的新 Observable 中的新 OnSubscribe,即在 lift() 中生成的那个 OnSubscribe

    4. 4.而这个新 OnSubscribecall() 方法中的 onSubscribe ,就是指的原始 Observable 中的原始 OnSubscribe ,在这个 call() 方法里,新 OnSubscribe 利用 operator.call(subscriber) 生成了一个新的 SubscriberOperator 就是在这里,通过自己的 call() 方法将新 Subscriber 和原始 Subscriber 进行关联,并插入自己的『变换』代码以实现变换),然后利用这个新 Subscriber 向原始 Observable 进行订阅。

    5. 这样就实现了 lift() 过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。

  2. 两次 lift

    精简掉细节的话,也可以这么说:在 Observable 执行了 lift(Operator) 方法之后,会返回一个新的 Observable,这个新的 Observable 会像一个代理一样,负责接收原始的 Observable 发出的事件,并在处理后发送给 Subscriber

    如果你更喜欢具象思维,可以看图:

    lift() 原理图

    或者可以看动图:

    两次和多次的 lift() 同理,如下图:两次 lift

 

 

subscribeOn() 和 observeOn() 的内部实现,也是用的 lift()。具体看图(不同颜色的箭头表示不同的线程):

subscribeOn() 原理图:

subscribeOn() 原理

observeOn() 原理图:

observeOn() 原理

从图中可以看出,subscribeOn() 和 observeOn() 都做了线程切换的工作(图中的 "schedule..." 部位)。不同的是, subscribeOn()的线程切换发生在 OnSubscribe 中,即在它通知上一级 OnSubscribe 时,这时事件还没有开始发送,因此 subscribeOn() 的线程控制可以从事件发出的开端就造成影响;而 observeOn() 的线程切换则发生在它内建的 Subscriber 中,即发生在它即将给下一级 Subscriber 发送事件时,因此 observeOn() 控制的是它后面的线程。

最后,我用一张图来解释当多个 subscribeOn() 和 observeOn() 混合使用时,线程调度是怎么发生的(由于图中对象较多,相对于上面的图对结构做了一些简化调整):

线程控制综合调用

 

 

 

为什么subscribeOn() 进行了接收线程的切换,发射线程仅仅响应了第一个 newThread,但每调用一次 observeOn() ,线程便会切换一次。subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。

我们来了解一下其订阅与数据传递的流程

 

RxJava的订阅与数据传递流程

订阅过程:从下往上

1.终点Observer订阅了map返回的ObserableMap。

2.map的Observable(ObservableMap)被订阅时,会订阅其上游的Observable,用于订阅上游的Observer是一个装饰者(MapObserver),内部保存了下游Observer,上游发数据时,传递给下游。

3.以此类推,源头Observable被订阅时,他会向Observer发数据

数据传递过程:从上往下

1.源头Observable传递数据给下游Observer

2.Observer收到数据对其变换的操作之后(就是Function执行之后),在调用内部保存的下游Observer的onNext()发送数据给下游

3.以此类推,最终把数据送达至终点Observer

 

通过对这两个流程的理解,你会发现,订阅是从下往上,所以第一个subscribeOn()最后被调用,所以无论你调用多少次,只响应第一个。同理,数据的发送是自上而下的,最下面,就是最后一个observeOn()被调用被最后调用,所以无论你调用多少次,都会响应最后一次;

 

你可能感兴趣的:(RxJava 2.x 教程及源码揭秘(四)由设计模式,揭秘Rxjava流程原理)