基本概念

rxjava 中的设计模式 rxjava interval_RxJava2


1.首先要掌握观察者模式,最常用的设计模式之一。RxJava就是基于观察者模式的

2.RxJava的特性

名称

解释

异步

RxJava是基于异步操作的框架,常用的应用场景有网络访问、数据解析等。

链式操作

RxJava提供了当前最主流的链式编程,其方式类似于构建者模式。

线程切换

RxJava提供了线程切换的功能,可以任意的在UI线程和工作线程中切换。

丰富的操作符

RxJava提供了丰富的操作符,简化了我们对方法或数据的操作。

背压策略

RxJava针对网络访问的高并发性,提供了背压的策略进行处理。

3.RxJava的基本概念

名称

解释

事件流

通过发射器发射的事件,从发射事件到结束事件的过程,这一过程称为事件流

数据流

通过发射器发射的数据,从数据输入到数据输出的过程,这一过程称为数据流

被观察者

事件流的上游,即Observable,事件流开始的地方和数据流发射的地方

观察者

事件流的下游,即Observer,事件流结束的地方和数据流接收的地方

4.创建操作符

名称

解释

create()

创建最简单的事件流

from()

创建事件流,可发送不同类型的数据流

just()

创建事件流,可发送多个参数的数据流

defer()

创建事件流,可缓存可激活事件流

interval()

创建延时重复的事件流

range()

创建事件流,可发送范围内的数据流

repeat()

创建可重复次数的事件流

timer()

创建一次延时的事件流

补充:interval()、timer()、delay()的区别
interval():用于创建事件流,周期性重复发送
timer():用于创建事件流,延时发送一次
delay():用于事件流中,可以延时某次事件流的发送

5.转换操作符

名称

解释

map()

对数据流的类型进行转换

flatMap()

对数据流的类型进行包装成另一个数据流

concatMap()

concatMap与flatMap功能一样,唯一的区别就是concatMap是有序的,flatMap是乱序的

groupby()

对所有的数据流进行分组

scan()

对上一轮处理过后的数据流进行函数处理

buffer()

缓存发射的数据流到一定数量,随后发射出数据流集合

window()

缓存发射的数据流到一定数量,随后发射出新的事件流

6.过滤操作符

名称

解释

debounce()

事件流只发射规定范围时间内的数据项

distinct()

事件流只发射不重复的数据项

elementAt()

事件流只发射第N个数据项

filter()

事件流只发射符合规定函数的数据项

first()

事件流只发射第一个数据项

ignoreElements()

忽略事件流的发射,只发射事件流的终止事件

last()

事件流只发射最后一项数据项

sample()

事件流对指定的时间间隔进行数据项的采样

skip()

事件流忽略前N个数据项

skipLast()

事件流忽略后N个数据项

take()

事件流只发射前N个数据项

takeLast()

事件流只发射后N个数据项

7.组合操作符

名称

解释

merge()/concat()

无序/有序的合并两个数据流

zip()

两个数据流的数据项合并成一个数据流一同发出

startWith()

将待合并的数据流放在自身前面一同发出

join()

将数据流进行排列组合发出,不过数据流都是有时间期限的

combineLatest()

合并最近发射出的数据项成数据流一同发出

8.错误处理操作符

名称

解释

onErrorReturn()

当错误发生时,它会忽略onError的回调且会发射一个新的数据项并回调onCompleted()

onErrorResumeNext()

当错误发生时,它会忽略onError的回调且会发射一个新的事件流并回调onCompleted()

onExceptionResumeNext()

当错误发生时,如果onError收到的Throwable不是一个Exception,它会回调onError方法,且不会回调备用的事件流,如果onError收到的Throwable是一个Exception,它会回调备用的事件流进行数据的发射

retry()

当错误发生时,发射器会重新发射

retryWhen()

当错误发生时,根据Tharowble类型决定发射器是否重新发射

9.辅助性操作符

名称

解释

delay()

延迟事件发射的数据项

do()

监听事件流的生命周期

materialize()/dematerialize()

对事件流进行装箱/拆箱

serialize()

同步事件流的发射

timeInterval()

对事件流增加时间间隔

timeout()

对事件流增加限定时间

timestamp()

对事件流增加时间戳

using()

对事件流增加一次性的资源

to()

对数据流中的数据项进行集合的转换

10.条件和布尔操作符

名称

解释

all()

对所有数据项进行校验

contains()

所有数据项是否包含指定数据项

amb()

多个事件流中,只发射最先发出的事件流

defaultIfEmpty()

如果数据流为空则发射默认数据项

sequenceEqual()

判断两个数据流是否完全相等

skipUntil()

当两个事件流发射时,第一个事件流的数据项会等到第二个事件流开始发射时才进行发射

skipWhile()

当发射的数据流达到某种条件时,才开始发射剩余所有数据项

takeUntil()

当两个事件流发射时,第一个事件流的数据项会等到第二个事件流开始发射时终止发射

takeWhile()

当发射的数据流达到某种条件时,才停止发射剩余所有数据项

11.数学运算及聚合操作符

名称

解释

average()

求所有数据项的平均值

max/min()

求所有数据项的最大或最小值

sum()

求所有数据项的总和

reduce()

对上一轮处理过后的数据流进行函数处理,只返回最后的结果

collect()

对上一轮处理过后的数据流进行函数处理,可改变原始的数据结构

12.连接操作符

名称

解释

publish()

将普通的事件流转换成可连接的事件流

connect()

将可连接的事件流进行连接并发射数据

refCount()

将可连接的事件流转换成普通的事件流

replay()

缓存可连接的事件流中的所有数据项

13.RxJava基本响应类型

名称

解释

Observable

Observable是最基本的响应类型,但不支持背压,基本上适用大多数的应用场景

Flowable

Flowable和Observable的使用基本相同,只不过Observable不支持背压,而Flowable支持背压。但需要注意的是,使用Flowable的时候,必须调用Subscription的requsest方法请求,不然上游是不会发射数据的

Single

Single只发射一个元素,发射onSuccess或onError方法,所以没有complete方法,不像Observable或者Flowable,数据发射完成之后,需要调用complete告诉下游已经完成

Completable

Completable不会发射数据,只会给下游发送一个信号。回调onComplete或onError方法

Maybe

Maybe是Single和Completable的结合,需要注意的是onSuccess和onComplete方法只会执行其中一个,这不同于Observable和Flowable最后是以onComplete()结尾

14.背压是什么

背压的概念是在平时业务开发时较为常见,大多数是针对高并发的业务,背压是必须考虑的因素之一。
在异步场景中,由于数据流的发射速度高于数据流的接收速度,就会导致数据不能及时处理,从而导致数据流的阻塞。背压所要做的事情就是主动控制数据流发射的速度。

15.RxJava2.0的背压简介

1.在订阅的时候如果使用FlowableSubscriber,那么需要通过s.request(Long.MAX_VALUE)去主动请求上游的数据项。如果遇到背压报错的时候,FlowableSubscriber默认已经将错误try-catch,并通过onError()进行回调,程序并不会崩溃

2.在订阅的时候如果使用Consumer,那么不需要主动去请求上游数据,默认已经调用了s.request(Long.MAX_VALUE)。如果遇到背压报错、且对Throwable的Consumer没有new出来,则程序直接崩溃

3.背压策略的上游的默认缓存池是128

16.常见的几个策略

名称

解释

MISSING

没有任何缓存和丢弃,下游要处理任何溢出

ERROR

下游的处理速度无法跟上上游的发射速度时报错

BUFFER

数据项的缓存池无限大

DROP

下游的处理速度无法跟上上游的发射速度时丢弃

LATEST

最后一条数据项被强行放入缓存池

详细说明:

名称

解释

MISSING

MISSING表示OnNext事件没有任何缓存和丢弃,下游要处理任何溢出,可以理解为相当于没有指定背压策略。Flowable相当于没有指定背压策略可以将下游要处理任何溢出理解为,上游发射的数据未得到处理,就会缓存起来,当缓存容量达到128时,再增加一个未处理的数据项,就会抛出MissingBackpressureException,且带有队列已经满了的友好提示。这里就好比一个大水缸,当水注满的时候,它就会把盖子盖上,不让你再继续注水了

ERROR

ERROR表示在下游无法跟上时,会抛出MissingBackpressureException。可以将下游无法跟上理解为,上游发射的数据未得到处理,就会缓存起来,当缓存容量达到128时,再增加一个未处理的数据项,就会抛出MissingBackpressureException。这里好比一个大水缸,当水注满的时候,它会把水缸撑破了,直接破裂

BUFFER

上游不断的发出onNext请求,直到下游处理完,上游发射的数据项的缓存池是无限大的,程序也不会抛出错误,但是要注意程序OOM的现象,因为缓存越大,占用的内存就越多。例子中发射129个数据项,然而程序并没有崩溃,只会一直读取缓存池的数据项,直到数据项被处理完。这里就是一个无限大的水缸

DROP

会在下游跟不上速度时,把onNext的值丢弃,简单的说就是,超过缓存区大小(128)的数据项都会被丢弃。例子中通过发射800个数据项,那么我们只会收到0-127的数据项。如果我们再次调用request(),这时候取到的数据就是上一次request()后的128个数据。这里好比一个大水缸,当水注满的时候,水还是在继续的流,一旦有request调用的时候,它就会去取出水缸里的所有水,这时候水缸就是空的,但水一直在流,所以水缸马上又会被注满,这个时候就要等request再次取出水缸里的水

LATEST

LATEST与Drop策略一样,如果超过缓存池容量大小的数据项都会被丢弃。不同的是,不管缓存池的状态如何,LATEST都会将最后一条数据强行放入缓存池中。这里的水缸容纳下了最后一滴水