ReactiveX使用介绍

3,921 阅读4分钟

ReactiveX是一个用观察者模式开发异步基于事件编程的库。

它扩展了观察者模式,支持流式的数据和事件,然后增加一些操作符可以用于灵活的处理流式数据与事件。其内置了很多不同类型的操作符,并且声明式的写法,让我们可以专注开发业务而无需考虑很多底层的线程,并发,非阻塞操作。

概念

什么是流式事件?

从事件维度上看,就是在不同时间依次发生的事件。比如说依次点击屏幕,如下可以看做流式的事件。stream of event或者event flow

img

为什么使用观察者模式(Observable)?

观察者模型,让我们在处理异步事件流时更加简单,就是提高效率。可以减少写很多的回调操作

单条数据(single items) 多条数据(multi items)
同步/synchronous T getData() Iterable getData()
异步/asynchronous Future getData() Observable getData()

如上图可以看出来,JDK本身没有提供对多条数据的异步支持。比如异步的返回,A,B,C三个东西,顺序不做要求,那么一般就要写三个Future。如果三个数据在同一个线程内处理,就是同步的。

Observable提供了一种理想化的方式来访问异步的流式数据(asynchronous sequences of multiple items)

Observables可以进行组合

Java的Future是一种直接的方式来处理单个异步的操作,但是如果嵌套使用Future的时候,在异步里面继续异步Future,代码就容易变得复杂不易维护。

组合多个Future进行异步化的条件执行下一步操作时,写法比较难优化。如果使用了Future.get可以更容易预测到结果,但是又过早的进入了阻塞。

ReactiveX Observables意在组合流式的异步数据。

Observables更加灵活

ReactiveX Observables不仅仅支持单个的数值,同时支持无限的数据流,无限数据流即永远都一直有新的数据出现,无法处理到最后。

上面提到了Observables是一种理想的方式处理异步的多个数据。其余同步的集合迭代器对比如下:

数据(event) Iterable (pull) Observable (push)
获取数据 T next() onNext(T)
发现错误 throws Exception onError(Exception)
完成处理 !hasNext() onCompleted()

相比于同步集合的pull数据,Observable是异步的push数据。

  • 使用Iterable,当没有数据到达的时候会进入阻塞状态。
  • 使用Observable,只要有数据可用的时候,就将数据推送给consumer,不管值是有还是没有,是同步还是异步。

Observable在经典的观察者模式中添加了两个新的语法,功能更强大灵活,并且也使得其写法与Iterable保持统一,让我们写Observable的时候就像在写Iterable:

  • 当生产者数据被消耗完毕的时候,Observable调用Observer的onCompleted方法
  • 当消费者在遇到错误或异常的时候,Observable调用Observer的onError方法

再看下Observable与Iterable的写法对比: 写法上没太大的变化,这里的Iterable可以看做Java 8中的Stream。

image-20191212072820313

Observable的灵活还有其不关心其数据源的如何实现,不管是使用线程池,actors,event loop或者其它内容,在Observable看来都是异步的。

使用ReactiveX时,可以修改底层的Observable实现而不需要修改Observable的Consumer代码。

使用

ReactiveX更像是一种理念,常见的编程语言都有关于ReactiveX的实现。以Java的实现RxJava为例。

写一个简单的Hello World案例:

1 引入Maven。

        <dependency>
            <groupId>io.reactivex.rxjava2</groupId>
            <artifactId>rxjava</artifactId>
            <version>2.2.12</version>
        </dependency>

2 编写Rxjava相关代码

public class RxHello {
    public static void main(String[] args) {
        // 1. 创建Observable
        Flowable<String> observable = Flowable
                .just("hello", "world")
                // 2. 使用Operator
                .map(String::toUpperCase)
                ;

        //3. 创建Observer
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println("收到数据:" + s);
            }
        };

        // 4. 建立订阅关系
        observable.subscribe(consumer);
    }
}    

上面代码看起来比较简单,实际上写的时候也确实比较简单,主要步骤就三步:加上操作符可以说是4步

1 创建Observable,ReactiveX提供了一些不同的Operator来创建,具体有没有实现要到对应的编程语言中看:

// 以下operator是可以创建
`Create`, `Defer`, `Empty`/`Never`/`Throw`, `From`, `Interval`, `Just`, `Range`, `Repeat`, `Start`, and `Timer
			
			// 比如:
        Observable.create();
        Observable.defer();
        Observable.just();
        Observable.fromArray()

2 进行Observable的数据处理,内置了非常多的操作符。转换,过滤,统计,错误处理等等

常见的Map,FlatMap,Filter,Take,Skip等

3 创建Observer,即观察者或者消费者,用于接收Observable的数据

常见的类:FlowableSubscriber,Subscriber,Comsumer,主要是我们的代码逻辑。

4 建立Observable和Observer的关系。

最后

这里只是介绍了ReactiveX的概念,介绍关键异步流式数据,与观察者模式部分,提供了案例代码,了解ReactiveX的基本写法。

想要提要到ReactiveX的强大,还需要掌握其丰富的Operator操作符功能。

参考:

reactivex.io/intro.html

reactivex.io/documentati…

medium.com/@andrestalt…