Rxjava操作符四

Distinct

抑制(过滤掉)重复的数据项

distinct

Distinct的过滤规则是:只允许还没有发射过的数据项通过。

在某些实现中,有一些变体允许你调整判定两个数据不同(distinct)的标准。还有一些实现只比较一项数据和它的直接前驱,因此只会从序列中过滤掉连续重复的数据。

distinct()

distinct

RxJava将这个操作符实现为distinct函数。

示例代码

Observable.just(1, 2, 1, 1, 2, 3)
          .distinct()
          .subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 1
Next: 2
Next: 3
Sequence complete.
  • Javadoc: distinct()

distinct(Func1)

distinct

这个操作符有一个变体接受一个函数。这个函数根据原始Observable发射的数据项产生一个Key,然后,比较这些Key而不是数据本身,来判定两个数据是否是不同的。

  • Javadoc: distinct(Func1)

distinctUntilChanged

distinctUntilChanged

RxJava还是实现了一个distinctUntilChanged操作符。它只判定一个数据和它的直接前驱是否是不同的。

distinctUntilChanged(Func1)

distinctUntilChanged.key

distinct(Func1)一样,根据一个函数产生的Key判定两个相邻的数据项是不是不同的。

  • Javadoc: distinctUntilChanged(Func1)

distinctdistinctUntilChanged默认不在任何特定的调度器上执行。

ElementAt

只发射第N项数据

elementAt

ElementAt操作符获取原始Observable发射的数据序列指定索引位置的数据项,然后当做自己的唯一数据发射。

elementAt

RxJava将这个操作符实现为elementAt,给它传递一个基于0的索引值,它会发射原始Observable数据序列对应索引位置的值,如果你传递给elementAt的值为5,那么它会发射第六项的数据。

如果你传递的是一个负数,或者原始Observable的数据项数小于index+1,将会抛出一个IndexOutOfBoundsException异常。

  • Javadoc: elementAt(int)

elementAtOrDefault

elementAtOrDefault

RxJava还实现了elementAtOrDefault操作符。与elementAt的区别是,如果索引值大于数据项数,它会发射一个默认值(通过额外的参数指定),而不是抛出异常。但是如果你传递一个负数索引值,它仍然会抛出一个IndexOutOfBoundsException异常。

  • Javadoc: elementAtOrDefault(int,T)

elementAtelementAtOrDefault默认不在任何特定的调度器上执行。

Filter

只发射通过了谓词测试的数据项

filter

Filter操作符使用你指定的一个谓词函数测试数据项,只有通过测试的数据才会被发射。

filter

RxJava将这个操作符实现为filter函数。

示例代码

Observable.just(1, 2, 3, 4, 5)
          .filter(new Func1() {
              @Override
              public Boolean call(Integer item) {
                return( item < 4 );
              }
          }).subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 1
Next: 2
Next: 3
Sequence complete.

filter默认不在任何特定的调度器上执行。

  • Javadoc: filter(Func1)

ofType

ofType

ofTypefilter操作符的一个特殊形式。它过滤一个Observable只返回指定类型的数据。

ofType默认不在任何特定的调度器上指定。

  • Javadoc: ofType(Class)

First

只发射第一项(或者满足某个条件的第一项)数据

first

如果你只对Observable发射的第一项数据,或者满足某个条件的第一项数据感兴趣,你可以使用First操作符。

在某些实现中,First没有实现为一个返回Observable的过滤操作符,而是实现为一个在当时就发射原始Observable指定数据项的阻塞函数。在这些实现中,如果你想要的是一个过滤操作符,最好使用Take(1)或者ElementAt(0)

在一些实现中还有一个Single操作符。它的行为与First类似,但为了确保只发射单个值,它会等待原始Observable终止(否则,不是发射那个值,而是以一个错误通知终止)。你可以使用它从原始Observable获取第一项数据,而且也确保只发射一项数据。

在RxJava中,这个操作符被实现为firstfirstOrDefaulttakeFirst

可能容易混淆,BlockingObservable也有名叫firstfirstOrDefault的操作符,它们会阻塞并返回值,不是立即返回一个Observable。

还有几个其它的操作符执行类似的功能。

IgnoreElements

不发射任何数据,只发射Observable的终止通知

ignoreElements

IgnoreElements操作符抑制原始Observable发射的所有数据,只允许它的终止通知(onErroronCompleted)通过。

如果你不关心一个Observable发射的数据,但是希望在它完成时或遇到错误终止时收到通知,你可以对Observable使用ignoreElements操作符,它会确保永远不会调用观察者的onNext()方法。

RxJava将这个操作符实现为ignoreElements

  • Javadoc: ignoreElements()

ignoreElements默认不在任何特定的调度器上执行。

Last

只发射最后一项(或者满足某个条件的最后一项)数据

last

如果你只对Observable发射的最后一项数据,或者满足某个条件的最后一项数据感兴趣,你可以使用Last操作符。

在某些实现中,Last没有实现为一个返回Observable的过滤操作符,而是实现为一个在当时就发射原始Observable指定数据项的阻塞函数。在这些实现中,如果你想要的是一个过滤操作符,最好使用TakeLast(1)

在RxJava中的实现是lastlastOrDefault

可能容易混淆,BlockingObservable也有名叫lastlastOrDefault的操作符,它们会阻塞并返回值,不是立即返回一个Observable。

过滤操作符

last

只发射最后一项数据,使用没有参数的last操作符。

示例代码

Observable.just(1, 2, 3)
          .last()
          .subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 3
Sequence complete.
  • Javadoc: last()
last

这个版本的last也是接受一个谓词函数,返回一个发射原始Observable中满足条件的最后一项数据的Observable。

  • Javadoc: last(Func1)
last

lastOrDefaultlast类似,不同的是,如果原始Observable没有发射任何值,它发射你指定的默认值。

  • Javadoc: lastOrDefault(T)
last

这个版本的lastOrDefault可以接受一个谓词函数,如果有数据满足条件,返回的Observable就发射原始Observable满足条件的最后一项数据,否则发射默认值。

  • Javadoc: lastOrDefault(T)

lastlastOrDefault默认不在任何特定的调度器上执行。

Sample

定期发射Observable最近发射的数据项

sample

Sample操作符定时查看一个Observable,然后发射自上次采样以来它最近发射的数据。

在某些实现中,有一个ThrottleFirst操作符的功能类似,但不是发射采样期间的最近的数据,而是发射在那段时间内的第一项数据。

RxJava将这个操作符实现为samplethrottleLast

注意:如果自上次采样以来,原始Observable没有发射任何数据,这个操作返回的Observable在那段时间内也不会发射任何数据。

sample

sample(别名throttleLast)的一个变体按照你参数中指定的时间间隔定时采样(TimeUnit指定时间单位)。

sample的这个变体默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

  • Javadoc: sample(long,TimeUnit)和throttleLast(long,TimeUnit)
  • Javadoc: sample(long,TimeUnit,Scheduler)和throttleLast(long,TimeUnit,Scheduler)
sample

sample的这个变体每当第二个Observable发射一个数据(或者当它终止)时就对原始Observable进行采样。第二个Observable通过参数传递给sample

sample的这个变体默认不在任何特定的调度器上执行。

  • Javadoc: sample(Observable)
throttleFirst

throttleFirstthrottleLast/sample不同,在每个采样周期内,它总是发射原始Observable的第一项数据,而不是最近的一项。

throttleFirst操作符默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

  • Javadoc: throttleFirst(long,TimeUnit)
  • Javadoc: throttleFirst(long,TimeUnit,Scheduler)

Skip

抑制Observable发射的前N项数据

skip

使用Skip操作符,你可以忽略Observable'发射的前N项数据,只保留之后的数据。

skip

RxJava中这个操作符叫skipskip的这个变体默认不在任何特定的调度器上执行。

  • Javadoc: skip(int)
skip

skip的这个变体接受一个时长而不是数量参数。它会丢弃原始Observable开始的那段时间发射的数据,时长和时间单位通过参数指定。

skip的这个变体默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

  • Javadoc: skip(long,TimeUnit)
  • Javadoc: skip(long,TimeUnit,Scheduler)

SkipLast

抑制Observable发射的后N项数据

skipLast

使用SkipLast操作符修改原始Observable,你可以忽略Observable'发射的后N项数据,只保留前面的数据。

[图片上传失败...(image-b2ec0-1572187529963)]

使用SkipLast操作符,你可以忽略原始Observable发射的后N项数据,只保留之前的数据。注意:这个机制是这样实现的:延迟原始Observable发射的任何数据项,直到它发射了N项数据。

skipLast的这个变体默认不在任何特定的调度器上执行。

  • Javadoc: skipLast(int)
skipLast

还有一个skipLast变体接受一个时长而不是数量参数。它会丢弃在原始Observable的生命周期内最后一段时间内发射的数据。时长和时间单位通过参数指定。

注意:这个机制是这样实现的:延迟原始Observable发射的任何数据项,直到自这次发射之后过了给定的时长。

skipLast的这个变体默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

  • Javadoc: skipLast(long,TimeUnit)
  • Javadoc: skipLast(long,TimeUnit,Scheduler)

Take

只发射前面的N项数据

take

使用Take操作符让你可以修改Observable的行为,只返回前面的N项数据,然后发射完成通知,忽略剩余的数据。

take

RxJava将这个操作符实现为take函数。

如果你对一个Observable使用take(n)(或它的同义词limit(n))操作符,而那个Observable发射的数据少于N项,那么take操作生成的Observable不会抛异常或发射onError通知,在完成前它只会发射相同的少量数据。

示例代码

Observable.just(1, 2, 3, 4, 5, 6, 7, 8)
          .take(4)
          .subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 1
Next: 2
Next: 3
Next: 4
Sequence complete.

take(int)默认不任何特定的调度器上执行。

  • Javadoc: take(int)
take

take的这个变体接受一个时长而不是数量参数。它会丢发射Observable开始的那段时间发射的数据,时长和时间单位通过参数指定。

take的这个变体默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

  • Javadoc: take(long,TimeUnit)
  • Javadoc: take(long,TimeUnit,Scheduler)

TakeLast

发射Observable发射的最后N项数据

takeLast

使用TakeLast操作符修改原始Observable,你可以只发射Observable'发射的后N项数据,忽略前面的数据。

taskLast.n

takeLast

使用takeLast操作符,你可以只发射原始Observable发射的后N项数据,忽略之前的数据。注意:这会延迟原始Observable发射的任何数据项,直到它全部完成。

takeLast的这个变体默认不在任何特定的调度器上执行。

  • Javadoc: takeLast(int)

takeLast.t

takeLast

还有一个takeLast变体接受一个时长而不是数量参数。它会发射在原始Observable的生命周期内最后一段时间内发射的数据。时长和时间单位通过参数指定。

注意:这会延迟原始Observable发射的任何数据项,直到它全部完成。

takeLast的这个变体默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

takeLastBuffer

takeLast

还有一个操作符叫takeLastBuffer,它和takeLast类似,,唯一的不同是它把所有的数据项收集到一个List再发射,而不是依次发射一个。

  • Javadoc: takeLastBuffer(int)
  • Javadoc: takeLastBuffer(long,TimeUnit)
  • Javadoc: takeLastBuffer(long,TimeUnit,Scheduler)
  • Javadoc: takeLastBuffer(int,long,TimeUnit)
  • Javadoc: takeLastBuffer(int,long,TimeUnit,Scheduler)

结合操作

这个页面展示的操作符可用于组合多个Observables。

  • startWith( ) — 在数据序列的开头增加一项数据
  • merge( ) — 将多个Observable合并为一个
  • mergeDelayError( ) — 合并多个Observables,让没有错误的Observable都完成后再发射错误通知
  • zip( ) — 使用一个函数组合多个Observable发射的数据集合,然后再发射这个结果
  • and( ), then( ), and when( ) — (rxjava-joins) 通过模式和计划组合多个Observables发射的数据集合
  • combineLatest( ) — 当两个Observables中的任何一个发射了一个数据时,通过一个指定的函数组合每个Observable发射的最新数据(一共两个数据),然后发射这个函数的结果
  • join( ) and groupJoin( ) — 无论何时,如果一个Observable发射了一个数据项,只要在另一个Observable发射的数据项定义的时间窗口内,就将两个Observable发射的数据合并发射
  • switchOnNext( ) — 将一个发射Observables的Observable转换成另一个Observable,后者发射这些Observables最近发射的数据

(rxjava-joins) — 表示这个操作符当前是可选的rxjava-joins包的一部分,还没有包含在标准的RxJava操作符集合里

And/Then/When

使用Pattern和Plan作为中介,将两个或多个Observable发射的数据集合并到一起

and/then/when

And/Then/When操作符组合的行为类似于zip,但是它们使用一个中间数据结构。接受两个或多个Observable,一次一个将它们的发射物合并到Pattern对象,然后操作那个Pattern对象,变换为一个Plan。随后将这些Plan变换为Observable的发射物。

and/then/when

它们属于rxjava-joins模块,不是核心RxJava包的一部分

CombineLatest

当两个Observables中的任何一个发射了数据时,使用一个函数结合每个Observable发射的最近数据项,并且基于这个函数的结果发射数据。

combineLatest

CombineLatest操作符行为类似于zip,但是只有当原始的Observable中的每一个都发射了一条数据时zip才发射数据。CombineLatest则在原始的Observable中任意一个发射了数据时发射一条数据。当原始Observables的任何一个发射了一条数据时,CombineLatest使用一个函数结合它们最近发射的数据,然后发射这个函数的返回值。

combineLatest

RxJava将这个操作符实现为combineLatest,它接受二到九个Observable作为参数,或者单个Observables列表作为参数。它默认不在任何特定的调度器上执行。

  • Javadoc: combineLatest(List,FuncN)
  • Javadoc: combineLatest(Observable,Observable,Func2)

withLatestFrom

withLatestFrom

withLatestFrom操作符还在开发中,不是1.0版本的一部分。类似于combineLatest,但是只在单个原始Observable发射了一条数据时才发射数据。

Join

任何时候,只要在另一个Observable发射的数据定义的时间窗口内,这个Observable发射了一条数据,就结合两个Observable发射的数据。

join

Join操作符结合两个Observable发射的数据,基于时间窗口(你定义的针对每条数据特定的原则)选择待集合的数据项。你将这些时间窗口实现为一些Observables,它们的生命周期从任何一条Observable发射的每一条数据开始。当这个定义时间窗口的Observable发射了一条数据或者完成时,与这条数据关联的窗口也会关闭。只要这条数据的窗口是打开的,它将继续结合其它Observable发射的任何数据项。你定义一个用于结合数据的函数。

groupJoin

很多ReactiveX实现还有一个类似的GroupJoin操作符。

Most ReactiveX implementations that have a Join operator also have a GroupJoin operator that is similar, except that the function you define to combine items emitted by the two Observables pairs individual items emitted by the source Observable not with an item from the second Observable, but with an Observable that emits items from the second Observable that fall in the same window.

join

The join operator takes four parameters:

  1. the second Observable to combine with the source Observable
  2. a function that accepts an item from the source Observable and returns an Observable whose lifespan governs the duration during which that item will combine with items from the second Observable
  3. a function that accepts an item from the second Observable and returns an Observable whose lifespan governs the duration during which that item will combine with items from the first Observable
  4. a function that accepts an item from the first Observable and an item from the second Observable and returns an item to be emitted by the Observable returned from join

join默认不在任何特定的调度器上执行。

  • Javadoc: Join(Observable,Func1,Func1,Func2)

[图片上传失败...(image-2198cc-1572187529963)]

The groupJoin operator takes four parameters:

  1. the second Observable to combine with the source Observable
  2. a function that accepts an item from the source Observable and returns an Observable whose lifespan governs the duration during which that item will combine with items from the second Observable
  3. a function that accepts an item from the second Observable and returns an Observable whose lifespan governs the duration during which that item will combine with items from the first Observable
  4. a function that accepts an item from the first Observable and an Observable that emits items from the second Observable and returns an item to be emitted by the Observable returned from groupJoin

groupJoin默认不在任何特定的调度器上执行。

  • Javadoc: groupJoin(Observable,Func1,Func1,Func2)
st.join

可选的StringObservable类中也有一个join操作符。它将一个发射字符串序列的Observable转换为一个发射单个字符串的Observable,join操作符使用指定的定界符将全部单独的字符串连接起来。

Merge

合并多个Observables的发射物

merge

使用Merge操作符你可以将多个Observables的输出合并,就好像它们是一个单个的Observable一样。

Merge可能会让合并的Observables发射的数据交错(有一个类似的操作符Concat不会让数据交错,它会按顺序一个接着一个发射多个Observables的发射物)。

正如图例上展示的,任何一个原始Observable的onError通知会被立即传递给观察者,而且会终止合并后的Observable。

mergeDelayError

在很多ReactiveX实现中还有一个叫MergeDelayError的操作符,它的行为有一点不同,它会保留onError通知直到合并后的Observable所有的数据发射完成,在那时它才会把onError传递给观察者。

RxJava将它实现为merge, mergeWithmergeDelayError

merge

示例代码

Observable odds = Observable.just(1, 3, 5).subscribeOn(someScheduler);
Observable evens = Observable.just(2, 4, 6);

Observable.merge(odds, evens)
          .subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 1
Next: 3
Next: 5
Next: 2
Next: 4
Next: 6
Sequence complete.
  • Javadoc: merge(Iterable)
  • Javadoc: merge(Iterable,int)
  • Javadoc: [merge(Observable])
  • Javadoc: merge(Observable,Observable) (接受二到九个Observable)

除了传递多个Observable给merge,你还可以传递一个Observable列表List,数组,甚至是一个发射Observable序列的Observable,merge将合并它们的输出作为单个Observable的输出:

merge

如果你传递一个发射Observables序列的Observable,你可以指定merge应该同时订阅的Observable'的最大数量。一旦达到订阅数的限制,它将不再订阅原始Observable发射的任何其它Observable,直到某个已经订阅的Observable发射了onCompleted通知。

  • Javadoc: merge(Observable)
  • Javadoc: merge(Observable,int)

merge是静态方法,mergeWith是对象方法,举个例子,Observable.merge(odds,evens)等价于odds.mergeWith(evens)

如果传递给merge的任何一个的Observable发射了onError通知终止了,merge操作符生成的Observable也会立即以onError通知终止。如果你想让它继续发射数据,在最后才报告错误,可以使用mergeDelayError

merge

mergeDelayError behaves much like merge. The exception is when one of the Observables being merged terminates with an onError notification. If this happens with merge, the merged Observable will immediately issue an onError notification and terminate. mergeDelayError, on the other hand, will hold off on reporting the error until it has given any other non-error-producing Observables that it is merging a chance to finish emitting their items, and it will emit those itself, and will only terminate with an onErrornotification when all of the other merged Observables have finished.

Because it is possible that more than one of the merged Observables encountered an error, mergeDelayError may pass information about multiple errors in the onError notification (it will never invoke the observer’s onError method more than once). For this reason, if you want to know the nature of these errors, you should write your observers’ onError methods so that they accept a parameter of the class CompositeException.

mergeDelayError has fewer variants. You cannot pass it an Iterable or Array of Observables, but you can pass it an Observable that emits Observables or between one and nine individual Observables as parameters. There is not an instance method version of mergeDelayError as there is for merge.

  • Javadoc: mergeDelayError(Observable)
  • Javadoc: mergeDelayError(Observable,Observable)

StartWith

在数据序列的开头插入一条指定的项

startWith

如果你想要一个Observable在发射数据之前先发射一个指定的数据序列,可以使用StartWith操作符。(如果你想一个Observable发射的数据末尾追加一个数据序列可以使用Concat操作符。)

startWith

可接受一个Iterable或者多个Observable作为函数的参数。

  • Javadoc: startWith(Iterable)
  • Javadoc: startWith(T) (最多接受九个参数)
startWith

你也可以传递一个Observable给startWith,它会将那个Observable的发射物插在原始Observable发射的数据序列之前,然后把这个当做自己的发射物集合。这可以看作是Concat的反转。

  • Javadoc: startWith(Observable)

Switch

将一个发射多个Observables的Observable转换成另一个单独的Observable,后者发射那些Observables最近发射的数据项

switch

Switch订阅一个发射多个Observables的Observable。它每次观察那些Observables中的一个,Switch返回的这个Observable取消订阅前一个发射数据的Observable,开始发射最近的Observable发射的数据。注意:当原始Observable发射了一个新的Observable时(不是这个新的Observable发射了一条数据时),它将取消订阅之前的那个Observable。这意味着,在后来那个Observable产生之后到它开始发射数据之前的这段时间里,前一个Observable发射的数据将被丢弃(就像图例上的那个黄色圆圈一样)。

Java将这个操作符实现为switchOnNext。它默认不在任何特定的调度器上执行。

  • Javadoc: switchOnNext(Observable)

Zip

通过一个函数将多个Observables的发射物结合到一起,基于这个函数的结果为每个结合体发射单个数据项。

zip

Zip操作符返回一个Obversable,它使用这个函数按顺序结合两个或多个Observables发射的数据项,然后它发射这个函数返回的结果。它按照严格的顺序应用这个函数。它只发射与发射数据项最少的那个Observable一样多的数据。

RxJava将这个操作符实现为zipzipWith

zip

zip的最后一个参数接受每个Observable发射的一项数据,返回被压缩后的数据,它可以接受一到九个参数:一个Observable序列,或者一些发射Observable的Observables。

  • Javadoc: zip(Iterable,FuncN)
  • Javadoc: zip(Observable,FuncN)
  • Javadoc: zip(Observable,Observable,Func2) (最多可以有九个Observables参数)

zipWith

zip

zipWith操作符总是接受两个参数,第一个参数是一个Observable或者一个Iterable。

  • Javadoc: zipWith(Observable,Func2)
  • Javadoc: zipWith(Iterable,Func2)

zipzipWith默认不在任何特定的操作符上执行。

错误处理

很多操作符可用于对Observable发射的onError通知做出响应或者从错误中恢复,例如,你可以:

  1. 吞掉这个错误,切换到一个备用的Observable继续发射数据
  2. 吞掉这个错误然后发射默认值
  3. 吞掉这个错误并立即尝试重启这个Observable
  4. 吞掉这个错误,在一些回退间隔后重启这个Observable

这是操作符列表:

  • onErrorResumeNext( ) — 指示Observable在遇到错误时发射一个数据序列
  • onErrorReturn( ) — 指示Observable在遇到错误时发射一个特定的数据
  • onExceptionResumeNext( ) — instructs an Observable to continue emitting items after it encounters an exception (but not another variety of throwable)指示Observable遇到错误时继续发射数据
  • retry( ) — 指示Observable遇到错误时重试
  • retryWhen( ) — 指示Observable遇到错误时,将错误传递给另一个Observable来决定是否要重新给订阅这个Observable

Catch

onError通知中恢复发射数据

catch

Catch操作符拦截原始Observable的onError通知,将它替换为其它的数据项或数据序列,让产生的Observable能够正常终止或者根本不终止。

在某些ReactiveX的实现中,有一个叫onErrorResumeNext的操作符,它的行为与Catch相似。

RxJava将Catch实现为三个不同的操作符:

onErrorReturn

让Observable遇到错误时发射一个特殊的项并且正常终止。

onErrorResumeNext

让Observable在遇到错误时开始发射第二个Observable的数据序列。

onExceptionResumeNext

让Observable在遇到错误时继续发射后面的数据项。

onErrorReturn

onErrorReturn

onErrorReturn方法返回一个镜像原有Observable行为的新Observable,后者会忽略前者的onError调用,不会将错误传递给观察者,作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法。

  • Javadoc: onErrorReturn(Func1)

onErrorResumeNext

onErrorResumeNext

onErrorResumeNext方法返回一个镜像原有Observable行为的新Observable,后者会忽略前者的onError调用,不会将错误传递给观察者,作为替代,它会开始镜像另一个,备用的Observable。

  • Javadoc: onErrorResumeNext(Func1)
  • Javadoc: onErrorResumeNext(Observable)

onExceptionResumeNext

onExceptionResumeNext

onErrorResumeNext类似,onExceptionResumeNext方法返回一个镜像原有Observable行为的新Observable,也使用一个备用的Observable,不同的是,如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。

  • Javadoc: onExceptionResumeNext(Observable)

Retry

如果原始Observable遇到错误,重新订阅它期望它能正常终止

retry

Retry操作符不会将原始Observable的onError通知传递给观察者,它会订阅这个Observable,再给它一次机会无错误地完成它的数据序列。Retry总是传递onNext通知给观察者,由于重新订阅,可能会造成数据项重复,如上图所示。

RxJava中的实现为retryretryWhen

无论收到多少次onError通知,无参数版本的retry都会继续订阅并发射原始Observable。

接受单个count参数的retry会最多重新订阅指定的次数,如果次数超了,它不会尝试再次订阅,它会把最新的一个onError通知传递给它的观察者。

还有一个版本的retry接受一个谓词函数作为参数,这个函数的两个参数是:重试次数和导致发射onError通知的Throwable。这个函数返回一个布尔值,如果返回trueretry应该再次订阅和镜像原始的Observable,如果返回falseretry会将最新的一个onError通知传递给它的观察者。

retry操作符默认在trampoline调度器上执行。

  • Javadoc: retry()
  • Javadoc: retry(long)
  • Javadoc: retry(Func2)

retryWhen

retryWhen

retryWhenretry类似,区别是,retryWhenonError中的Throwable传递给一个函数,这个函数产生另一个Observable,retryWhen观察它的结果再决定是不是要重新订阅原始的Observable。如果这个Observable发射了一项数据,它就重新订阅,如果这个Observable发射的是onError通知,它就将这个通知传递给观察者然后终止。

retryWhen默认在trampoline调度器上执行,你可以通过参数指定其它的调度器。

示例代码

Observable.create((Subscriber s) -> {
      System.out.println("subscribing");
      s.onError(new RuntimeException("always fails"));
  }).retryWhen(attempts -> {
      return attempts.zipWith(Observable.range(1, 3), (n, i) -> i).flatMap(i -> {
          System.out.println("delay retry by " + i + " second(s)");
          return Observable.timer(i, TimeUnit.SECONDS);
      });
  }).toBlocking().forEach(System.out::println);

输出

subscribing
delay retry by 1 second(s)
subscribing
delay retry by 2 second(s)
subscribing
delay retry by 3 second(s)
subscribing
  • Javadoc: retryWhen(Func1)
  • Javadoc: retryWhen(Func1,Scheduler)

辅助操作

这个页面列出了很多用于Observable的辅助操作符

  • materialize( ) — 将Observable转换成一个通知列表convert an Observable into a list of Notifications
  • dematerialize( ) — 将上面的结果逆转回一个Observable
  • timestamp( ) — 给Observable发射的每个数据项添加一个时间戳
  • serialize( ) — 强制Observable按次序发射数据并且要求功能是完好的
  • cache( ) — 记住Observable发射的数据序列并发射相同的数据序列给后续的订阅者
  • observeOn( ) — 指定观察者观察Observable的调度器
  • subscribeOn( ) — 指定Observable执行任务的调度器
  • doOnEach( ) — 注册一个动作,对Observable发射的每个数据项使用
  • doOnCompleted( ) — 注册一个动作,对正常完成的Observable使用
  • doOnError( ) — 注册一个动作,对发生错误的Observable使用
  • doOnTerminate( ) — 注册一个动作,对完成的Observable使用,无论是否发生错误
  • doOnSubscribe( ) — 注册一个动作,在观察者订阅时使用
  • doOnUnsubscribe( ) — 注册一个动作,在观察者取消订阅时使用
  • finallyDo( ) — 注册一个动作,在Observable完成时使用
  • delay( ) — 延时发射Observable的结果
  • delaySubscription( ) — 延时处理订阅请求
  • timeInterval( ) — 定期发射数据
  • using( ) — 创建一个只在Observable生命周期存在的资源
  • single( ) — 强制返回单个数据,否则抛出异常
  • singleOrDefault( ) — 如果Observable完成时返回了单个数据,就返回它,否则返回默认数据
  • toFuture( ), toIterable( ), toList( ) — 将Observable转换为其它对象或数据结构

Delay

延迟一段指定的时间再发射来自Observable的发射物

delay

Delay操作符让原始Observable在发射每项数据之前都暂停一段指定的时间段。效果是Observable发射的数据项在时间上向前整体平移了一个增量。

RxJava的实现是 delaydelaySubscription

delay

第一种delay接受一个定义时长的参数(包括数量和单位)。每当原始Observable发射一项数据,delay就启动一个定时器,当定时器过了给定的时间段时,delay返回的Observable发射相同的数据项。

注意:delay不会平移onError通知,它会立即将这个通知传递给订阅者,同时丢弃任何待发射的onNext通知。然而它会平移一个onCompleted通知。

delay默认在computation调度器上执行,你可以通过参数指定使用其它的调度器。

  • Javadoc: delay(long,TimeUnit)
  • Javadoc: delay()
delay

另一种delay不实用常数延时参数,它使用一个函数针对原始Observable的每一项数据返回一个Observable,它监视返回的这个Observable,当任何那样的Observable终止时,delay返回的Observable就发射关联的那项数据。

这种delay默认不在任何特定的调度器上执行。

  • Javadoc: delay(Func1)
delay

这个版本的delay对每一项数据使用一个Observable作为原始Observable的延时定时器。

这种delay默认不在任何特定的调度器上执行。

  • Javadoc: delay(Func0,Func1)
delay

还有一个操作符delaySubscription让你你可以延迟订阅原始Observable。它结合搜一个定义延时的参数。

delaySubscription默认在computation调度器上执行,你可以通过参数指定使用其它的调度器。

  • Javadoc: delaySubscription(long,TimeUnit)
  • Javadoc: delaySubscription(long,TimeUnit,Scheduler)
delay

还有一个版本的delaySubscription使用一个Obseable而不是一个固定的时长来设置订阅延时。

这种delaySubscription默认不在任何特定的调度器上执行。

  • Javadoc: delaySubscription(Func0)

Do

注册一个动作作为原始Observable生命周期事件的一种占位符

do

你可以注册回调,当Observable的某个事件发生时,Rx会在与Observable链关联的正常通知集合中调用它。Rx实现了多种操作符用于达到这个目的。

RxJava实现了很多Do操作符的变体。

doOnEach

doOnEach

doOnEach操作符让你可以注册一个回调,它产生的Observable每发射一项数据就会调用它一次。你可以以Action的形式传递参数给它,这个Action接受一个onNext的变体Notification作为它的唯一参数,你也可以传递一个Observable给doOnEach,这个Observable的onNext会被调用,就好像它订阅了原始的Observable一样。

  • Javadoc: doOnEach(Action1)
  • Javadoc: doOnEach(Observer)

doOnNext

doOnNext

doOnNext操作符类似于doOnEach(Action1),但是它的Action不是接受一个Notification参数,而是接受发射的数据项。

示例代码

Observable.just(1, 2, 3)
          .doOnNext(new Action1() {
          @Override
          public void call(Integer item) {
            if( item > 1 ) {
              throw new RuntimeException( "Item exceeds maximum value" );
            }
          }
        }).subscribe(new Subscriber() {
        @Override
        public void onNext(Integer item) {
            System.out.println("Next: " + item);
        }

        @Override
        public void onError(Throwable error) {
            System.err.println("Error: " + error.getMessage());
        }

        @Override
        public void onCompleted() {
            System.out.println("Sequence complete.");
        }
    });

输出

Next: 1
Error: Item exceeds maximum value

doOnSubscribe

doOnSubscribe

doOnSubscribe操作符注册一个动作,当观察者订阅它生成的Observable它就会被调用。

  • Javadoc: doOnSubscribe(Action0)

doOnUnsubscribe

doOnUnsubscribe

doOnUnsubscribe操作符注册一个动作,当观察者取消订阅它生成的Observable它就会被调用。

  • Javadoc: doOnUnsubscribe(Action0)

doOnCompleted

doOnCompleted

doOnCompleted 操作符注册一个动作,当它产生的Observable正常终止调用onCompleted时会被调用。

  • Javadoc: doOnCompleted(Action0)

doOnError

doOnError

doOnError 操作符注册一个动作,当它产生的Observable异常终止调用onError时会被调用。

  • Javadoc: doOnError(Action0)

doOnTerminate

doOnTerminate

doOnTerminate 操作符注册一个动作,当它产生的Observable终止之前会被调用,无论是正常还是异常终止。

  • Javadoc: doOnTerminate(Action0)

finallyDo

finallyDo

finallyDo 操作符注册一个动作,当它产生的Observable终止之后会被调用,无论是正常还是异常终止。

  • Javadoc: finallyDo(Action0)

Materialize/Dematerialize

Materialize将数据项和事件通知都当做数据项发射,Dematerialize刚好相反。

materialize

一个合法的有限的Obversable将调用它的观察者的onNext方法零次或多次,然后调用观察者的onCompletedonError正好一次。Materialize操作符将这一系列调用,包括原来的onNext通知和终止通知onCompletedonError都转换为一个Observable发射的数据序列。

RxJava的materialize将来自原始Observable的通知转换为Notification对象,然后它返回的Observable会发射这些数据。

materialize默认不在任何特定的调度器 (Scheduler) 上执行。

  • Javadoc: materialize()
dematerialize

Dematerialize操作符是Materialize的逆向过程,它将Materialize转换的结果还原成它原本的形式。

dematerialize反转这个过程,将原始Observable发射的Notification对象还原成Observable的通知。

dematerialize默认不在任何特定的调度器 (Scheduler) 上执行。

  • Javadoc: dematerialize()

ObserveOn

指定一个观察者在哪个调度器上观察这个Observable

observeOn

很多ReactiveX实现都使用调度器 "Scheduler"来管理多线程环境中Observable的转场。你可以使用ObserveOn操作符指定Observable在一个特定的调度器上发送通知给观察者 (调用观察者的onNext, onCompleted, onError方法)。

observeOn

注意:当遇到一个异常时ObserveOn会立即向前传递这个onError终止通知,它不会等待慢速消费的Observable接受任何之前它已经收到但还没有发射的数据项。这可能意味着onError通知会跳到(并吞掉)原始Observable发射的数据项前面,正如图例上展示的。

SubscribeOn操作符的作用类似,但它是用于指定Observable本身在特定的调度器上执行,它同样会在那个调度器上给观察者发通知。

RxJava中,要指定Observable应该在哪个调度器上调用观察者的onNext, onCompleted, onError方法,你需要使用observeOn操作符,传递给它一个合适的Scheduler

  • Javadoc: observeOn(Scheduler)

Serialize

强制一个Observable连续调用并保证行为正确

img

一个Observable可以异步调用它的观察者的方法,可能是从不同的线程调用。这可能会让Observable行为不正确,它可能会在某一个onNext调用之前尝试调用onCompletedonError方法,或者从两个不同的线程同时调用onNext方法。使用Serialize操作符,你可以纠正这个Observable的行为,保证它的行为是正确的且是同步的。

RxJava中的实现是serialize,它默认不在任何特定的调度器上执行。

  • Javadoc: serialize()

Subscribe

操作来自Observable的发射物和通知

Subscribe操作符是连接观察者和Observable的胶水。一个观察者要想看到Observable发射的数据项,或者想要从Observable获取错误和完成通知,它首先必须使用这个操作符订阅那个Observable。

Subscribe操作符的一般实现可能会接受一到三个方法(然后由观察者组合它们),或者接受一个实现了包含这三个方法的接口的对象(有时叫做ObserverSubscriber):

onNext

每当Observable发射了一项数据它就会调用这个方法。这个方法的参数是这个Observable发射的数据项。

onError

Observable调用这个方法表示它无法生成期待的数据或者遇到了其它错误。这将停止Observable,它在这之后不会再调用onNextonCompletedonError方法的参数是导致这个错误的原因的一个表示(有时可能是一个Exception或Throwable对象,其它时候也可能是一个简单的字符串,取决于具体的实现)。

onCompleted

如果没有遇到任何错误,Observable在最后一次调用onCompleted之后会调用这个方法。

如果一个Observable直到有一个观察者订阅它才开始发射数据项,就称之为"冷"的Observable;如果一个Observable可能在任何时刻开始发射数据,就称之为"热"的Observable,一个订阅者可能从开始之后的某个时刻开始观察它发射的数据序列,它可能会错过在订阅之前发射的数据。

RxJava中的实现是subscribe方法。

如果你使用无参数的版本,它将触发对Observable的一个订阅,但是将忽略它的发射物和通知。这个操作会激活一个"冷"的Observable。

你也可以传递一到三个函数给它,它们会按下面的方法解释:

  1. onNext
  2. onNextonError
  3. onNext, onErroronCompleted

最后,你还可以传递一个ObserverSubscriber接口给它,Observer接口包含这三个以on开头的方法。Subscriber接口也实现了这三个方法,而且还添加了几个额外的方法,用于支持使用反压操作(reactive pull backpressure),这让Subscriber可以在Observable完成前取消订阅。

subscribe方法返回一个实现了Subscription接口的对象。这个接口包含unsubscribe方法,任何时刻你都可以调用它来断开subscribe方法建立的Observable和观察者之间的订阅关系。

  • Javadoc: subscribe()
  • Javadoc: subscribe(Action1)
  • Javadoc: subscribe(Action1,Action1)
  • Javadoc: subscribe(Action1,Action1,Action0)
  • Javadoc: subscribe(Observer)
  • Javadoc: subscribe(Subscriber)

foreach

forEach方法是简化版的subscribe,你同样可以传递一到三个函数给它,解释和传递给subscribe时一样。

不同的是,你无法使用forEach返回的对象取消订阅。也没办法传递一个可以用于取消订阅的参数。因此,只有当你明确地需要操作Observable的所有发射物和通知时,你才应该使用这个操作符。

  • Javadoc: forEach(Action1)
  • Javadoc: forEach(Action1,Action1)
  • Javadoc: forEach(Action1,Action1,A/Users/mcxiaoke/github/RxDocs/docs/BlockingObservable.mdction0)

BlockingObservable

BlockingObservable类中也有一个类似的叫作forEach的方法。详细的说明见 BlockingObservable

SubscribeOn

指定Observable自身在哪个调度器上执行

SubscribeOn

很多ReactiveX实现都使用调度器 "Scheduler"来管理多线程环境中Observable的转场。你可以使用SubscribeOn操作符指定Observable在一个特定的调度器上运转。

ObserveOn操作符的作用类似,但是功能很有限,它指示Observable在一个指定的调度器上给观察者发通知。

在某些实现中还有一个UnsubscribeOn操作符。

  • Javadoc: subscribeOn(Scheduler)
  • Javadoc: unsubscribeOn(Scheduler)

TimeInterval

将一个发射数据的Observable转换为发射那些数据发射时间间隔的Observable

TimeInterval

TimeInterval操作符拦截原始Observable发射的数据项,替换为发射表示相邻发射物时间间隔的对象。

RxJava中的实现为timeInterval,这个操作符将原始Observable转换为另一个Observable,后者发射一个标志替换前者的数据项,这个标志表示前者的两个连续发射物之间流逝的时间长度。新的Observable的第一个发射物表示的是在观察者订阅原始Observable到原始Observable发射它的第一项数据之间流逝的时间长度。不存在与原始Observable发射最后一项数据和发射onCompleted通知之间时长对应的发射物。

timeInterval默认在immediate调度器上执行,你可以通过传参数修改。

  • Javadoc: timeInterval()
  • Javadoc: timeInterval(Scheduler)

Timeout

对原始Observable的一个镜像,如果过了一个指定的时长仍没有发射数据,它会发一个错误通知

Timeout

如果原始Observable过了指定的一段时长没有发射任何数据,Timeout操作符会以一个onError通知终止这个Observable。

RxJava中的实现为timeout,但是有好几个变体。

Timeout

第一个变体接受一个时长参数,每当原始Observable发射了一项数据,timeout就启动一个计时器,如果计时器超过了指定指定的时长而原始Observable没有发射另一项数据,timeout就抛出TimeoutException,以一个错误通知终止Observable。

这个timeout默认在computation调度器上执行,你可以通过参数指定其它的调度器。

  • Javadoc: timeout(long,TimeUnit)
  • Javadoc: timeout()
Timeout

这个版本的timeout在超时时会切换到使用一个你指定的备用的Observable,而不是发错误通知。它也默认在computation调度器上执行。

  • Javadoc: timeout(long,TimeUnit,Observable)
  • Javadoc: timeout(long,TimeUnit,Observable,Scheduler)
Timeout

这个版本的timeout使用一个函数针对原始Observable的每一项返回一个Observable,如果当这个Observable终止时原始Observable还没有发射另一项数据,就会认为是超时了,timeout就抛出TimeoutException,以一个错误通知终止Observable。

这个timeout默认在immediate调度器上执行。

  • Javadoc: timeout(Func1)
Timeout

这个版本的timeout同时指定超时时长和备用的Observable。它默认在immediate调度器上执行。

  • Javadoc: timeout(Func1,Observable)
Timeout

这个版本的time除了给每一项设置超时,还可以单独给第一项设置一个超时。它默认在immediate调度器上执行。

  • Javadoc: timeout(Func0,Func1)
Timeout

同上,但是同时可以指定一个备用的Observable。它默认在immediate调度器上执行。

  • Javadoc: timeout(Func0,Func1,Observable)

Timestamp

给Observable发射的数据项附加一个时间戳

Timestamp

RxJava中的实现为timestamp,它将一个发射T类型数据的Observable转换为一个发射类型为Timestamped的数据的Observable,每一项都包含数据的原始发射时间。

timestamp默认在immediate调度器上执行,但是可以通过参数指定其它的调度器。

  • Javadoc: timestamp()
  • Javadoc: timestamp(Scheduler)

Using

创建一个只在Observable生命周期内存在的一次性资源

using

Using操作符让你可以指示Observable创建一个只在它的生命周期内存在的资源,当Observable终止时这个资源会被自动释放。

using

using操作符接受三个参数:

  1. 一个用户创建一次性资源的工厂函数
  2. 一个用于创建Observable的工厂函数
  3. 一个用于释放资源的函数

当一个观察者订阅using返回的Observable时,using将会使用Observable工厂函数创建观察者要观察的Observable,同时使用资源工厂函数创建一个你想要创建的资源。当观察者取消订阅这个Observable时,或者当观察者终止时(无论是正常终止还是因错误而终止),using使用第三个函数释放它创建的资源。

using默认不在任何特定的调度器上执行。

  • Javadoc: using(Func0,Func1,Action1)

To

将Observable转换为另一个对象或数据结构

to

ReactiveX的很多语言特定实现都有一种操作符让你可以将Observable或者Observable发射的数据序列转换为另一个对象或数据结构。它们中的一些会阻塞直到Observable终止,然后生成一个等价的对象或数据结构;另一些返回一个发射那个对象或数据结构的Observable。

在某些ReactiveX实现中,还有一个操作符用于将Observable转换成阻塞式的。一个阻塞式的Ogbservable在普通的Observable的基础上增加了几个方法,用于操作Observable发射的数据项。

getIterator

getIterator

getIterator操作符只能用于BlockingObservable的子类,要使用它,你首先必须把原始的Observable转换为一个BlockingObservable。可以使用这两个操作符:BlockingObservable.fromthe Observable.toBlocking

这个操作符将Observable转换为一个Iterator,你可以通过它迭代原始Observable发射的数据集。

  • Javadoc: BlockingObservable.getIterator()

toFuture

toFuture

toFuture操作符也是只能用于BlockingObservable。这个操作符将Observable转换为一个返回单个数据项的Future,如果原始Observable发射多个数据项,Future会收到一个IllegalArgumentException;如果原始Observable没有发射任何数据,Future会收到一个NoSuchElementException

如果你想将发射多个数据项的Observable转换为Future,可以这样用:myObservable.toList().toBlocking().toFuture()

  • Javadoc: BlockingObservable.toFuture()

toIterable

toIterable

toFuture操作符也是只能用于BlockingObservable。这个操作符将Observable转换为一个Iterable,你可以通过它迭代原始Observable发射的数据集。

  • Javadoc: BlockingObservable.toIterable()

toList

toList

通常,发射多项数据的Observable会为每一项数据调用onNext方法。你可以用toList操作符改变这个行为,让Observable将多项数据组合成一个List,然后调用一次onNext方法传递整个列表。

如果原始Observable没有发射任何数据就调用了onCompletedtoList返回的Observable会在调用onCompleted之前发射一个空列表。如果原始Observable调用了onErrortoList返回的Observable会立即调用它的观察者的onError方法。

toList默认不在任何特定的调度器上执行。

  • Javadoc: toList()

toMap

toMap

toMap收集原始Observable发射的所有数据项到一个Map(默认是HashMap)然后发射这个Map。你可以提供一个用于生成Map的Key的函数,还可以提供一个函数转换数据项到Map存储的值(默认数据项本身就是值)。

toMap默认不在任何特定的调度器上执行。

  • Javadoc: toMap(Func1)
  • Javadoc: toMap(Func1,Func1)
  • Javadoc: toMap(Func1,Func1,Func0)

toMultiMap

toMultiMap

toMultiMap类似于toMap,不同的是,它生成的这个Map同时还是一个ArrayList(默认是这样,你可以传递一个可选的工厂方法修改这个行为)。

toMultiMap默认不在任何特定的调度器上执行。

  • Javadoc: toMultiMap(Func1)
  • Javadoc: toMultiMap(Func1,Func1)
  • Javadoc: toMultiMap(Func1,Func1,Func0)
  • Javadoc: toMultiMap(Func1,Func1,Func0,Func1)

toSortedList

toSortedList

toSortedList类似于toList,不同的是,它会对产生的列表排序,默认是自然升序,如果发射的数据项没有实现Comparable接口,会抛出一个异常。然而,你也可以传递一个函数作为用于比较两个数据项,这是toSortedList不会使用Comparable接口。

toSortedList默认不在任何特定的调度器上执行。

  • Javadoc: toSortedList()
  • Javadoc: toSortedList(Func2)

Rxjava操作符五

你可能感兴趣的:(Rxjava操作符四)