1 RxJava介绍
Java平台上有一个用于响应式编程的标准库,即RxJava 1.1。正如我们今天在Java世界中知道的那样,该库为响应式编程铺平了道路。目前,它不是唯一的响应式库,我们还有Akka Streams和Project Reactor。
RxJava是一个非常著名的开源库,是ReactiveX(Reactive Extensions)的一种Java实现,。ReactiveX是一种响应式扩展框架,有很多种实现,如RxAndroid、RxJS、RxSwift、RxRuby、RxCpp、RxGo等。
Reactive Extensions是一组工具,能用命令式语言处理数据流,无论该流是同步的还是异步的。ReactiveX通常被定义为观察者模式、迭代器模式和函数式编程的组合。
目前RxJava有1.x和2.x两个主要的分支,分别代表着RxJava 1和RxJava 2。由于RxJava 1发布的时间较早,使用也更广泛,但是RxJava 2已经发布,以后也会逐渐流行起来。
RxJava 1.的生命周期结束于2018年3月,但它仍然被用于很多库和应用程序。
2 RxJava核心角色和入门程序
2.1 核心角色
- Observer接口,类似于观察者模式中的观察者
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
这是RxJava的基本概念。此接口定义了数据如何在响应式流的每个部分之间进行流动。作为库的最小组成部分,Observer接口随处可见
-
Subscriber抽象类(订阅者/观察者,实现了Observer):实现Observer接口并消费元素,还被用作Subscriber的实际实现的基础。Observable和Subscriber之间的运行时关系由Subscription控制,Subscription可以检查订阅状态并在必要时取消它。
-
Observable类,类似于观察者模式的中的Subject角色,Observable扮演事件源的角色,它会发出元素。它有数百种流转换方法以及几十种初始化响应式流的工厂方法。
2.2 入门程序
- 常见可观察的对象(主题)Observable
// 创建一个Observable并使其带有一个回调
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
// call方法将在订阅者出现时立即被触发
@Override
public void call(Subscriber<? super String> subscriber) {
// Observer将产生一个字符串值,订阅者通过onNext获得字符串
subscriber.onNext("hello rx java 1");
subscriber.onNext("hello rx java 2");
subscriber.onNext("hello rx java 3");
// 模拟异常
// int a = 10/0;
subscriber.onNext("hello rx java 4");
subscriber.onNext("hello rx java 5");
// 结束信号发送给订阅者
subscriber.onCompleted();
}
});
可见就是通过OnSubscribe接口的call方法,将观察者(订阅者)和Observable建立了关系。
注意,从RxJava 1.2.7开始,Observable的创建已因不安全而被弃用。这是因为它可能生成太多元素,导致订阅者超载。
- 实现一个订阅者
// 订阅者
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("done");
}
@Override
public void onError(Throwable e) {
System.err.println("发生了异常 -> " + e.getClass().getSimpleName() + " : " +e.getMessage());
}
@Override
public void onNext(String s) {
System.out.println(s.toUpperCase());
}
};
- 将可观察对象和订阅者建立关系
// 添加订阅者
observable.subscribe(subscriber);
- 完整的代码:
public static void main(String[] args) {
// 创建一个Observable并使其带有一个回调
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
// call方法将在订阅者出现时立即被触发
@Override
public void call(Subscriber<? super String> subscriber) {
// Observer将产生一个字符串值,订阅者通过onNext获得字符串
subscriber.onNext("hello rx java 1");
subscriber.onNext("hello rx java 2");
subscriber.onNext("hello rx java 3");
// 模拟异常
// int a = 10/0;
subscriber.onNext("hello rx java 4");
subscriber.onNext("hello rx java 5");
// 结束信号发送给订阅者
subscriber.onCompleted();
}
});
// 订阅者
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("done");
}
@Override
public void onError(Throwable e) {
System.err.println("发生了异常 -> " + e.getClass().getSimpleName() + " : " +e.getMessage());
}
@Override
public void onNext(String s) {
System.out.println(s.toUpperCase());
}
};
// 添加订阅者
observable.subscribe(subscriber);
// 主线程阻塞
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行输出:
HELLO RX JAVA 1
HELLO RX JAVA 2
HELLO RX JAVA 3
HELLO RX JAVA 4
HELLO RX JAVA 5
done
将模拟异常的代码放开,则输出如下:
HELLO RX JAVA 1
HELLO RX JAVA 2
HELLO RX JAVA 3
发生了异常 -> ArithmeticException : / by zero
使用lambda表达式简化:
public static void main(String[] args) {
Observable.create((subscriber)->{
subscriber.onNext("hello rx java 1");
subscriber.onNext("hello rx java 2");
subscriber.onNext("hello rx java 3");
// 模拟异常
// int a = 10/0;
subscriber.onNext("hello rx java 4");
subscriber.onNext("hello rx java 5");
// 结束信号发送给订阅者
subscriber.onCompleted();
subscriber.onNext("hello rx java 6");
}).subscribe(
System.out::println,
System.err::println,
() -> System.out.println("Done!"));
// 主线程阻塞
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}