文章目录
前言
现在我们可以看到越来越多的开发者都在使用 Rx 相关的技术进行 App,Java 后端等领域进行开发。在开源的社区以及互联网公司,Rx、响应式编程、函数式都是热门的存在。所以笔者将结合自身的学习以及实际使用情况,写一个针对 Rxjava2 的系列文章,一起学习和使用 Rxjava 所带来的便捷。
笔者将利用工作之余,结合 ReactiveX 官方 Wiki
对 Rxjava 的定义与介绍,对相关基础知识、基本操作,常用部分的 API
进行整理,并加上个人理解和相关操作的示例。
相关参考链接:
Rxjava2 系列文章目录:
- Rxjava2 介绍与详解实例
- Rxjava2 Observable的创建详解及实例
- Rxjava2 Observable的数据变换详解及实例(一)
- Rxjava2 Observable的数据变换详解及实例(二)
- Rxjava2 Observable的数据过滤详解及实例(一)
- Rxjava2 Observable的数据过滤详解及实例(二)
- Rxjava2 Observable的结合操作详解及实例
- Rxjava2 可连接的Observable(ConnectableObservable)操作详解及实例
- Rxjava2 Observable的错误处理操作详解及实例
- Rxjava2 Observable的辅助操作详解及实例(一)
- Rxjava2 Observable的辅助操作详解及实例(二)
- Rxjava2 Observable的条件操作符详解及实例
- Rxjava2 Observable的布尔操作符详解及实例
未完,待续(正在努力整理中)...
实例代码:
RX介绍
ReactiveX的历史
ReactiveX
是Reactive Extensions的缩写,一般简写为Rx,最初是LINQ的一个扩展,由微软的架构师Erik Meijer领导的团队开发,在2012年11月开源,Rx是一个编程模型,目标是提供一致的编程接口,帮助开发者更方便的处理异步数据流,Rx库支持.NET、JavaScript和C++,Rx近几年越来越流行了,现在已经支持几乎全部的流行编程语言了,Rx的大部分语言库由ReactiveX这个组织负责维护,比较流行的有RxJava/RxJS/Rx.NET,社区网站是reactivex.io。
什么是ReactiveX
微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。
ReactiveX.io给的定义是,Rx是一个使用可观察数据流进行异步编程
的编程接口,ReactiveX结合了观察者模式
、迭代器模式
和函数式编程
的精华。
RxJava 到底是什么
RxJava 在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。
然而,对于初学者来说,这还是比较含蓄难懂的。因为它是一个总结
,而初学者更需要一个入门的介绍或者理解。其实, RxJava 的本质可以总结为异步
的概念。说到本质上,它就是一个实现异步操作的库。RxJava 的异步实现,是通过一种扩展的观察者模式
来实现的。
RxJava 优点
同样是做异步,为什么去使用它,而不用现成的 Thread,ThreadPoolExecutor,Android的AsyncTask / Handler / … ?其实就是简洁,易用
!
异步操作很关键的一点是程序的简洁性,因为在调度过程比较复杂的情况下,异步代码经常会既难写也难被读懂。 正如Android 创造的 AsyncTask 和Handler ,其实都是为了让异步代码更加简洁。RxJava 的优势也是简洁,但它的简洁的与众不同之处在于,随着程序逻辑变得越来越复杂,它依然能够保持简洁。
名词定义
- Reactive 直译为反应性的,有活性的,根据上下文一般翻译为反应式、响应式。
- Iterable 可迭代对象,支持以迭代器的形式遍历,许多语言中都存在这个概念。
- Observable 可观察对象,在Rx中定义为更强大的Iterable,在观察者模式中是被观察的对象,一旦数据产生或发生变化,会通过某种方式通知观察者或订阅者。
- Observer 观察者对象,监听Observable发射的数据并做出响应,Subscriber是它的一个特殊实现。
- emit 直译为发射,发布,发出,含义是Observable在数据产生或变化时发送通知给Observer,调用Observer对应的方法,文章里一律译为发射。
- items 直译为项目,条目,在Rx里是指Observable发射的数据项,文章里一律译为数据,数据项。
Rx模式
使用观察者模式
- 创建:Rx可以方便的创建事件流和数据流
- 组合:Rx使用查询式的操作符组合和变换数据流
- 监听:Rx可以订阅任何可观察的数据流并执行操作
简化代码
- 函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态
- 简化代码:Rx的操作符通通常可以将复杂的难题简化为很少的几行代码
- 异步错误处理:传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制
- 轻松使用并发:Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种
并发问题
使用Observable的优势
Rx扩展了观察者模式用于支持数据和事件序列,添加了一些操作符,它让你可以声明式的组合这些序列,而无需关注底层的实现:如线程、同步、线程安全、并发数据结构和非阻塞IO。
Observable通过使用最佳的方式访问异步数据序列填补了这个间隙。
类型 | 单个数据 | 多个数据 |
---|---|---|
同步 | T getData() | Iterable getData |
异步 | Future<T> getData() | Observable<T> getData() |
Rx的Observable模型让你可以像使用集合数据一样操作异步事件流,对异步事件流使用各种
简单、可组合的操作。
1. Observable可组合
对于单层的异步操作来说,Java中Future对象的处理方式是非常简单有效的,但是一旦涉及到嵌套,它们就开始变得异常繁琐和复杂。使用Future很难很好的组合带条件的异步执行流程(考虑到运行时各种潜在的问题,甚至可以说是不可能的),当然,要想实现还是可以做到的,但是非常困难,或许你可以用 Future.get() ,但这样做,异步执行的优势就完全没有了。从另一方面说,Rx的bservable一开始就是为组合异步数据流准备的。
2. Observable更灵活
Rx的Observable不仅支持处理单独的标量值(就像Future可以做的),也支持数据序列,甚至是无穷的数据流。 Observable 是一个抽象概念,适用于任何场景。Observable拥有它的近亲Iterable的全部优雅与灵活。
Observable是异步的双向push,Iterable是同步的单向pull,对比:
事件 | Iterable(pull) | Observable(push) |
---|---|---|
获取数据 | T next() | onNext(T) |
异常处理 | throws Exception | onError(Exception) |
任务完成 | !hasNext() | onCompleted |
3. Observable无偏见
Rx对于对于并发性或异步性没有任何特殊的偏好,Observable可以用任何方式实现,线程池、事件循环、非阻塞IO、Actor模式,任何满足你的需求的,你擅长或偏好的方式都可以。无论你选择怎样实现它,无论底层实现是阻塞的还是非阻塞的,客户端代码将所有与Observable的交互都当做是异步的。
Rx使用依赖:
下列是笔者使用的版本(可根据实际情况进行选择):
- 使用Gradle依赖:
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
- 使用Maven依赖或者Jar包下载 :Rxjava 2.2.12
- 其他版本以及相关下载 :Maven
Rxjava的入门基础
1. Observable
1.1 观察者模式
基本概念:Observable
(可观察者,即被观察者)、Observer
(观察者)、 subscribe
(订阅)、事件
。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer(观察者观察被观察者的通知事件)。
在RxJava中,一个实现了 Observer 接口的对象可以订阅 (subscribe) 一个 Observable 类的实例。订阅者(subscriber) 对 Observable 发射 (emit) 的任何数据或数据序列作出响应。这种模式 简化了并发操作,因为它不需要阻塞等待 Observable 发射数据,而是创建了一个处于待命状态的观察者哨兵,哨兵在未来某个时刻响应Observable的通知。
RxJava 的事件回调方法: onSubscribe()
、onNext()
、 onCompleted()
和 onError()
。
- onSubscribe(): 当被观察者被观察者订阅的时候触发。
- onNext(): 当被观察者发送数据的时候通过此方法通知观察者数据变换。
- onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
- onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
注意: 在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
1.2 Consumer 和 Action
这两个词意思分别是 消费者
(可以理解为消费被观察者发射出来的事件)和 行为
(可以理解为响应被观察者的行为)。对于 Observer 中的 4 个回调方法,我们未必都能用得到,如果只需要用到其中的一部分,就需要 Consumer 和 Action 上场了。
简单示例:
// 1. 进行订阅,subscribe(Observer)
observable.subscribe(observer);
System.out.println("---------------------------------------------");
// 2. 进行订阅,subscribe(Consumer onNext)
observable.subscribe(nextConsumer);
System.out.println("---------------------------------------------");
// 3. 进行订阅,subscribe(Consumer onNext, Consumer onError)
observable.subscribe(nextConsumer, errorConsumer);
System.out.println("---------------------------------------------");
// 4. 进行订阅,subscribe(Consumer onNext, Consumer onError, Action onCompleted)
observable.subscribe(nextConsumer, errorConsumer, completedAction);
System.out.println("---------------------------------------------");
// 5. 进行订阅,subscribe(Consumer onNext, Consumer onError, Action onCompleted, Consumer onSubscribe)
observable.subscribe(nextConsumer, errorConsumer, completedAction, onSubscribeComsumer);
1.3 Observable的分类
在RxJava中,Observable 有 Hot 与 Cold 之分。
- Hot Observable : 无论有没有观察者进行订阅,事件始终都会发生。当有多个观察者订阅时,Hot Observable此时与订阅者们的关系时一对多的关系,可以与多个订阅者共享信息。
- Cold Observable : 只有有观察者订阅了,才开始执行数据流的发送,并且与观察者时一对一的关系。当有多个不同的订阅者时,消息是重新完整发送的,也就是说对于订阅者们来说,它们的事件是彼此独立的。
Javadoc: Observable
2. Flowable
Rxjava2.x 中有这么一个被观察者 Flowable
,同样作为被观察者,它和Observable有什么区别呢,在Rxjava2中,Observable不再支持背压,而新增的Flowable支持背压,何为背压,就是异步场景
下上游发送事件的速度大于下游处理事件的速度所产生的现象。
提示:在本系列后面会有详细的单独篇章来介绍和如何使用背压。
Javadoc: Flowable
3. Single
Single
类似于 Observable,不同的是,它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。
因此,不同于Observable需要三个方法 onNext, onError, onCompleted,订阅Single只需要两个方法:
- onSuccess: Single发射单个的值到这个方法
- onError: 如果无法发射需要的值,Single发射一个Throwable对象到这个方法
Single 只会调用这两个方法中的一个,而且只会调用一次,调用了任何一个方法之后,订阅关系终止。
示例代码:
// Single: 只发送 onSuccess or onError 通知,并且只会发送一次, 第一次发送数据后的都不会在处理
Single.create(new SingleOnSubscribe<String>() {
@Override
public void subscribe(SingleEmitter<String> emitter) throws Exception {
emitter.onSuccess("Success"); // 发送success通知
emitter.onSuccess("Success2"); // 只能发送一次通知,后续不在处理
}
}).subscribe(new BiConsumer<String, Throwable>() {
@Override
public void accept(String t1, Throwable t2) throws Exception {
System.out.println("--> accept: t1 = " + t1 + ", t2 = " + t2);
}
});
输出:
--> accept: t1 = Success, t2 = null
提示:Single 可以通过
toXXX
方法转换为 Observable, Flowable, Completable与Maybe。
Javadoc: Single
4. Completable
Completable 在创建后,不会发射任何数据, 只有 onComplete
与 onError
事件,同时没有Observable中的一些操作符,如 map,flatMap。通常与 andThen
操作符结合使用。
示例代码:
// 1. Completable:只发送complete 或 error 事件,不发送任何数据
Completable.fromAction(new Action() {
@Override
public void run() throws Exception {
System.out.println("Hello World! This is Completable.");
}
}).subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("--> onSubscribe");
}
@Override
public void onError(Throwable e) {
System.out.println("--> onError");
}
@Override
public void