RxJava是一个基于事件流的实现异步操作的框架(库),其作用是实现异步操作,类似于Android中的AsyncTask,那么为什么RxJava可以在众多异步操作的库中脱颖而出深受广大开发者喜爱呢?原因在于其逻辑简单、使用方便、条理清晰的特点,本文将由浅至深、由易到难一步一步带你理解和使用RxJava。
本文目录如下:
RxJava原理初探
既然RxJava是为了异任务而引入的,那么我们首先引入一个生活中异步任务的小例子:假设小王周末要出去逛街,她出门以后用滴滴打车App叫了一个顺风车,然后顺风车主接到滴滴打车App派发的任务后开车去接小王,最后小王等到车,然后去开心的逛街之旅,整个事件的流程是这样的:
那么将上述例子抽象到代码层面,RxJava实现上述场景的原理是这样的,首先将一个完整的异步任务分为以下几个角色:
- 被观察者(Observable):作用是在合适的事件产生事件,在此处的实例中就是小王
- 观察者(Observer):接收事件,对事件进行处理,此处的实例中就是司机,处理事件的过程就是开车去接小王
- 订阅者(Subscribe):连接观察者与被观察者,在此实例中就是滴滴打车App,任务是将被观察者(小王)的事件请求(打车)发送到观察者(司机)处
- 事件(Event):具体的异步任务的载体,在此实例中指的就是打车
这样进行抽象的话我们就可以将上述实例的过程抽象为以下流程:
需要注意的一点是,被观察者可以连续发出多条事件请求给观察者,在此处由于实例限制只发送了一条事件(打车事件),但是在实际的应用场景中被观察者可以发送多条事件给观察者进行处理。总结一下RxJava的简要原理如下图所示:
从上图中我们应该明确:
- RxJava其实就是帮我们实现了一个更易用的观察者模式
- 被观察者可以发送给观察者多个事件,这也是RxJava被称为基于事件流的库的原因
- 观察者会顺序处理观察者接收到的事件
至此,我们就理清了RxJava的大概原理和理念,接下来我们来看看如何使用RxJava实现我们上述的实例。
RxJava入门使用
在使用之前请大家要先在自己的项目中添加RxJava的依赖:
dependencies {
implementation "io.reactivex.rxjava2:rxjava:2.2.10"
...
}
具体的实现我们分为两部分,第一部分是分步实现,旨在向大家说明RxJava的原理、让大家对RxJava的原理有更加深入的认识,第二部分是我们平时在生产中建议使用的、比较简洁的写法,需要注意的是这两部分都能实现相同的功能,大家根据自己的喜好在实际生产中选择对应方法即可。
分步实现
分布实现主要分为3步:
- 创建被观察者并且生产事件
- 创建观察者并监听事件
- 通过订阅将观察者和被观察者连接起来
创建被观察者并且生产事件
代码与注释齐飞更容易理解:
注意3点:
- 被观察者用来发送时间的发射器ObservableEmitter实现了Emitter接口,Emitter接口的源码如下(注意看注释):
- 请大家注意看注释,也就是说,被观察者可以发送三类事件:普通事件(Next事件)、异常事件(Error事件)、完结事件(Complete事件),普通事件就是我们一般需要发送给观察者处理的异步任务,异常事件一般是指当被观察者发现发生了某些异常时通知观察者所用的,完结事件的作用就是通知观察者所有时间已经发送完毕,相当于一个句号。
- Observable是一个泛型抽象类,此处我们实例化的是Observable<String>,但是在实际使用时我们可以使用任意类型,比如Observable<Integer>甚至你自己创建的自定义类;
- 在我们的实例中被观察者(小王)只打了一次车,即发送一次事件,但是为了说明RxJava事件流的特点,我这里发送了两次事件即打车事件1和打车事件2,大家不要奇怪;
创建观察者并监听事件
直接看代码,注意注释:
注意2点:
- 在观察者接收被观察者的事件(建立连接)之前,默认会先调用一次onSubscribe()方法
- 被观察者发送的普通事件(Next事件)、异常事件(Error事件)、完结事件(Complete事件)会依次被这的onNext()、onError()、onComplete()方法接收
通过订阅将观察者和被观察者连接起来
这一步比较简单:
直接调用被观察者(小王)的订阅方法(subscribe()),将观察者(司机)传入即可。
实际的运行效果如下:
基于事件流的链式调用
上一节的分步实现旨在向大家说明RxJava的原理,本节我将为大家介绍一种更加简洁的写法,即与事件流的链式调用法:
实际的运行效果如下:
可以看到,两种写法都可以达到相同的效果,但是很明显第二种写法更加简洁、条理更加清晰,更重要的是,随着程序逻辑的复杂性提高,它依然能够保持简洁和优雅。所以,一般建议使用这种基于事件流的链式调用方式实现RxJava。
如何切断观察者与被观察者之间的连接
有的时候我们可能需要在接收到某个事件之后切断观察者与被观察者之间的联系,这个时候就可以使用Disposable.dispose() 方法,比如:
运行结果如下:
可以看到,当使用Disposable.dispose() 将观察者与被观察者之间的连接切断后,后序的所有被观察者发送的事件都不会被观察者接收(不管是Next事件还是Error事件还是Complete事件),但是被观察者可以正常发送事件。