前言
那么本文就将对Rxjava做一次详细的探索,相信跟随着博主的思路带着自己的思考,你一定也能掌握使用这个热门技术的要领。不仅如此,我们更要深入了解其内部原理,做到知其然,并且知其所以然。
关于Rxjava的基本了解以及其使用,我在该系列的另一篇文章中已经介绍过了。详情关注
在另一篇文章中,从源码出发,了解了其内部流程,理解Rxjava是如何实现线程的切换以及对任务逻辑的一些加工,并保持其链式结构
RxJava 2.x 教程及源码揭秘(三)Rxjava操作符源码解析
本文将从设计模式的角度,带你完整地回顾一下RxJava整个流程中一些重要的点,让你彻底了解这个流行的工具库的内部原理
RxJava涉及的设计模式
-
观察者模式
采用注册(Register)或者称为订阅(Subscribe)的方式,告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。举个安卓中最典型的例子吧,我们空间的点击事件监听就是一种观察者模式,对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过 setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的 OnClickListener 。
采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
我们来对比下OnclickListener和RxJava


Buton持有OnClickListener的引用,当Button触发了点击事件,调用OnClickListene的OnClik方法,这就是观察者的流程,相信集合上面图片的对比,你已经知道了RxJava中各部分分别对应的角色。
RxJava 有四个基本概念:
Observable(可观察者,即被观察者)、Observer(观察者)、subscribe(订阅)、事件。Observable和Observer通过subscribe()方法实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer。-
装饰者模式
RxJava所有操作符的共同原理:lift()
这些变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法:
lift(Operator)。首先看一下lift()的内部实现(仅核心代码):// 注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。 // 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。 public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) { return Observable.create(new OnSubscribe<R>() { @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.而同样地,新
Observable里的新OnSubscribe加上之前的原始Observable中的原始OnSubscribe,也就有了两个OnSubscribe -
3.当用户调用经过
lift()后的Observable的subscribe()的时候,使用的是lift()所返回的新的Observable,于是它所触发的onSubscribe.call(subscriber),也是用的新Observable中的新OnSubscribe,即在lift()中生成的那个OnSubscribe; -
4.而这个新
OnSubscribe的call()方法中的onSubscribe,就是指的原始Observable中的原始OnSubscribe,在这个call()方法里,新OnSubscribe利用operator.call(subscriber)生成了一个新的Subscriber(Operator就是在这里,通过自己的call()方法将新Subscriber和原始Subscriber进行关联,并插入自己的『变换』代码以实现变换),然后利用这个新Subscriber向原始Observable进行订阅。 -
这样就实现了
lift()过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。
-
-

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

或者可以看动图:

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

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中观察者模式和装饰者模式的应用,详细解析lift()方法如何实现事件序列变换,以及subscribeOn()和observeOn()如何进行线程切换。通过流程图和动图,清晰展示RxJava的数据传递与订阅机制。

被折叠的 条评论
为什么被折叠?



