创建操作
Create
使用一个函数从头开始创建一个Observable
你可以使用Create
操作符从头开始创建一个Observable,给这个操作符传递一个接受观察者作为参数的函数,编写这个函数让它的行为表现为一个Observable--恰当的调用观察者的onNext,onError和onCompleted方法。
一个形式正确的有限Observable必须尝试调用观察者的onCompleted正好一次或者它的onError正好一次,而且此后不能再调用观察者的任何其它方法。
RxJava将这个操作符实现为 create
方法。
建议你在传递给create
方法的函数中检查观察者的isUnsubscribed
状态,以便在没有观察者的时候,让你的Observable停止发射数据或者做昂贵的运算。
示例代码:
Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super Integer> observer) {
try {
if (!observer.isUnsubscribed()) {
for (int i = 1; i < 5; i++) {
observer.onNext(i);
}
observer.onCompleted();
}
} catch (Exception e) {
observer.onError(e);
}
}
} ).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.
create
方法默认不在任何特定的调度器上执行。
- Javadoc:
create(OnSubscribe)
Defer
直到有观察者订阅时才创建Observable,并且为每个观察者创建一个新的Observable
Defer
操作符会一直等待直到有观察者订阅它,然后它使用Observable工厂方法生成一个Observable。它对每个观察者都这样做,因此尽管每个订阅者都以为自己订阅的是同一个Observable,事实上每个订阅者获取的是它们自己的单独的数据序列。
在某些情况下,等待直到最后一分钟(就是知道订阅发生时)才生成Observable可以确保Observable包含最新的数据。
RxJava将这个操作符实现为 defer
方法。这个操作符接受一个你选择的Observable工厂函数作为单个参数。这个函数没有参数,返回一个Observable。
defer
方法默认不在任何特定的调度器上执行。
- Javadoc:
defer(Func0)
switchCase
可选包 rxjava-computation-expressions
中有一个类似的操作符。switchCase
操作符有条件的创建并返回一个可能的Observables集合中的一个。
可选包 rxjava-computation-expressions
中还有一个更简单的操作符叫ifThen
。这个操作符检查某个条件,然后根据结果,返回原始Observable的镜像,或者返回一个空Observable。
Empty/Never/Throw
Empty
创建一个不发射任何数据但是正常终止的Observable
Never
创建一个不发射数据也不终止的Observable
Throw
创建一个不发射数据以一个错误终止的Observable
这三个操作符生成的Observable行为非常特殊和受限。测试的时候很有用,有时候也用于结合其它的Observables,或者作为其它需要Observable的操作符的参数。
RxJava将这些操作符实现为 empty
,never
和error
。error
操作符需要一个Throwable
参数,你的Observable会以此终止。这些操作符默认不在任何特定的调度器上执行,但是empty
和error
有一个可选参数是Scheduler,如果你传递了Scheduler参数,它们会在这个调度器上发送通知。
- Javadoc: empty()
- Javadoc: never()
- Javadoc: error(java.lang.Throwable)
From
将其它种类的对象和数据类型转换为Observable
[图片上传失败...(image-52a925-1572186452758)]
当你使用Observable时,如果你要处理的数据都可以转换成展现为Observables,而不是需要混合使用Observables和其它类型的数据,会非常方便。这让你在数据流的整个生命周期中,可以使用一组统一的操作符来管理它们。
例如,Iterable可以看成是同步的Observable;Future,可以看成是总是只发射单个数据的Observable。通过显式地将那些数据转换为Observables,你可以像使用Observable一样与它们交互。
因此,大部分ReactiveX实现都提供了将语言特定的对象和数据结构转换为Observables的方法。
在RxJava中,from
操作符可以转换Future、Iterable和数组。对于Iterable和数组,产生的Observable会发射Iterable或数组的每一项数据。
示例代码
Integer[] items = { 0, 1, 2, 3, 4, 5 };
Observable myObservable = Observable.from(items);
myObservable.subscribe(
new Action1() {
@Override
public void call(Integer item) {
System.out.println(item);
}
},
new Action1() {
@Override
public void call(Throwable error) {
System.out.println("Error encountered: " + error.getMessage());
}
},
new Action0() {
@Override
public void call() {
System.out.println("Sequence complete");
}
}
);
输出
0
1
2
3
4
5
Sequence complete
对于Future,它会发射Future.get()方法返回的单个数据。from
方法有一个可接受两个可选参数的版本,分别指定超时时长和时间单位。如果过了指定的时长Future还没有返回一个值,这个Observable会发射错误通知并终止。
from
默认不在任何特定的调度器上执行。然而你可以将Scheduler作为可选的第二个参数传递给Observable,它会在那个调度器上管理这个Future。
- Javadoc: from(array)
- Javadoc: from(Iterable)
- Javadoc: from(Future)
- Javadoc: from(Future,Scheduler)
- Javadoc: from(Future,timeout, timeUnit)
RxJavaAsyncUtil
此外,在可选包 RxJavaAsyncUtil
中,你还可以用下面这些操作符将actions,callables,functions和runnables转换为发射这些动作的执行结果的Observable:
- fromAction
- fromCallable
- fromFunc0
- fromRunnable
在这个页面 Start 查看关于这些操作符的更多信息。
注意:还有一个可选的StringObservable
类中也有一个from
方法,它将一个字符流或者一个REader转换为一个发射字节数组或字符串的Observable。
runAsync2
注意:这里与后面start
操作符里的runAsync
说明重复了
在单独的RxJavaAsyncUtil
包中(默认不包含在RxJava中),还有一个runAsync
函数。传递一个Action
和一个Scheduler
给runAsync
,它会返回一个StoppableObservable
,这个Observable使用Action
产生发射的数据项。
传递一个Action
和一个Scheduler
给runAsync
,它返回一个使用这个Action
产生数据的StoppableObservable
。这个Action
接受一个Observable
和一个Subscription
作为参数,它使用Subscription
检查unsubscribed
条件,一旦发现条件为真就立即停止发射数据。在任何时候你都可以使用unsubscribe
方法手动停止一个StoppableObservable
(这会同时取消订阅与这个StoppableObservable
关联的Subscription
)。
由于runAsync
会立即调用Action
并开始发射数据,在你创建StoppableObservable之后到你的观察者准备好接受数据之前这段时间里,可能会有一部分数据会丢失。如果这不符合你的要求,可以使用runAsync
的一个变体,它也接受一个Subject
参数,传递一个ReplaySubject
给它,你可以获取其它丢失的数据了。
decode
StringObservable
类不是默认RxJava的一部分,包含一个decode
操作符,这个操作符将一个多字节字符流转换为一个发射字节数组的Observable,这些字节数组按照字符的边界划分。
Interval
创建一个按固定时间间隔发射整数序列的Observable
Interval
操作符返回一个Observable,它按固定的时间间隔发射一个无限递增的整数序列。
RxJava将这个操作符实现为interval
方法。它接受一个表示时间间隔的参数和一个表示时间单位的参数。
- Javadoc: interval(long,TimeUnit)
- Javadoc: interval(long,TimeUnit,Scheduler)
还有一个版本的interval
返回一个Observable,它在指定延迟之后先发射一个零值,然后再按照指定的时间间隔发射递增的数字。这个版本的interval
在RxJava 1.0.0中叫做timer
,但是那个方法已经不建议使用了,因为一个名叫interval
的操作符有同样的功能。
Javadoc: interval(long,long,TimeUnit) Javadoc: interval(long,long,TimeUnit,Scheduler)
interval
默认在computation
调度器上执行。你也可以传递一个可选的Scheduler参数来指定调度器。
Just
创建一个发射指定值的Observable
Just将单个数据转换为发射那个数据的Observable。
Just类似于From,但是From会将数组或Iterable的数据取出然后逐个发射,而Just只是简单的原样发射,将数组或Iterable当做单个数据。
注意:如果你传递null
给Just,它会返回一个发射null
值的Observable。不要误认为它会返回一个空Observable(完全不发射任何数据的Observable),如果需要空Observable你应该使用Empty操作符。
RxJava将这个操作符实现为just
函数,它接受一至九个参数,返回一个按参数列表顺序发射这些数据的Observable。
示例代码:
Observable.just(1, 2, 3)
.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: just(item) (还有其它接受二到九个参数的版本)
Range
创建一个发射特定整数序列的Observable
Range操作符发射一个范围内的有序整数序列,你可以指定范围的起始和长度。
RxJava将这个操作符实现为range
函数,它接受两个参数,一个是范围的起始值,一个是范围的数据的数目。如果你将第二个参数设为0,将导致Observable不发射任何数据(如果设置为负数,会抛异常)。
range
默认不在任何特定的调度器上执行。有一个变体可以通过可选参数指定Scheduler。
- Javadoc: range(int,int)
- Javadoc: range(int,int,Scheduler)
Repeat
创建一个发射特定数据重复多次的Observable
Repeat重复地发射数据。某些实现允许你重复的发射某个数据序列,还有一些允许你限制重复的次数。
RxJava将这个操作符实现为repeat
方法。它不是创建一个Observable,而是重复发射原始Observable的数据序列,这个序列或者是无限的,或者通过repeat(n)
指定重复次数。
repeat
操作符默认在trampoline
调度器上执行。有一个变体可以通过可选参数指定Scheduler。
Javadoc: repeat() Javadoc: repeat(long) Javadoc: repeat(Scheduler) Javadoc: repeat(long,Scheduler)
repeatWhen
还有一个叫做repeatWhen
的操作符,它不是缓存和重放原始Observable的数据序列,而是有条件的重新订阅和发射原来的Observable。
将原始Observable的终止通知(完成或错误)当做一个void
数据传递给一个通知处理器,它以此来决定是否要重新订阅和发射原来的Observable。这个通知处理器就像一个Observable操作符,接受一个发射void
通知的Observable为输入,返回一个发射void
数据(意思是,重新订阅和发射原始Observable)或者直接终止(意思是,使用repeatWhen
终止发射数据)的Observable。
repeatWhen
操作符默认在trampoline
调度器上执行。有一个变体可以通过可选参数指定Scheduler。
- Javadoc: repeatWhen(Func1)
- Javadoc: repeatWhen(Func1,Scheduler)
doWhile
doWhile
属于可选包rxjava-computation-expressions
,不是RxJava标准操作符的一部分。doWhile
在原始序列的每次重复后检查某个条件,如果满足条件才重复发射。
whileDo
whileDo
属于可选包rxjava-computation-expressions
,不是RxJava标准操作符的一部分。whileDo
在原始序列的每次重复前检查某个条件,如果满足条件才重复发射
Start
返回一个Observable,它发射一个类似于函数声明的值
编程语言有很多种方法可以从运算结果中获取值,它们的名字一般叫functions, futures, actions, callables, runnables
等等。在Start
目录下的这组操作符可以让它们表现得像Observable,因此它们可以在Observables调用链中与其它Observable搭配使用。
Start
操作符的多种RxJava实现都属于可选的rxjava-async
模块。
rxjava-async
模块包含start
操作符,它接受一个函数作为参数,调用这个函数获取一个值,然后返回一个会发射这个值给后续观察者的Observable。
注意:这个函数只会被执行一次,即使多个观察者订阅这个返回的Observable。
toAsync
rxjava-async
模块还包含这几个操作符:toAsync
, asyncAction
, 和asyncFunc
。它们接受一个函数或一个Action作为参数。
对于函数(functions),这个操作符调用这个函数获取一个值,然后返回一个会发射这个值给后续观察者的Observable(和start
一样)。对于动作(Action),过程类似,但是没有返回值,在这种情况下,这个操作符在终止前会发射一个null
值。
注意:这个函数或动作只会被执行一次,即使多个观察者订阅这个返回的Observable。
startFuture
rxjava-async
模块还包含一个startFuture
操作符,传递给它一个返回Future
的函数,startFuture
会立即调用这个函数获取Future
对象,然后调用Future
的get()
方法尝试获取它的值。它返回一个发射这个值给后续观察者的Observable。
deferFuture
rxjava-async
模块还包含一个deferFuture
操作符,传递给它一个返回Future
的函数(这个Future
返回一个Observable
),deferFuture
返回一个Observable,但是不会调用你提供的函数,直到有观察者订阅它返回的Observable。这时,它立即调用Future
的get()
方法,然后镜像发射get()
方法返回的Observable发射的数据。
用这种方法,你可以在Observables调用链中包含一个返回Observable的Future
对象。
fromAction
rxjava-async
模块还包含一个fromAction
操作符,它接受一个Action
作为参数,返回一个Observable,一旦Action终止,它发射这个你传递给fromAction
的数据。
fromCallable
rxjava-async
模块还包含一个fromCallable
操作符,它接受一个Callable
作为参数,返回一个发射这个Callable
的结果的Observable。
fromRunnable
rxjava-async
模块还包含一个fromRunnable
操作符,它接受一个Runnable
作为参数,返回一个Observable,一旦Runnable终止,它发射这个你传递给fromRunnable
的数据。
forEachFuture
rxjava-async
模块还包含一个forEachFuture
操作符。它其实不算Start
操作符的一个变体,而是有一些自己的特点。你传递一些典型的观察者方法(如onNext, onError和onCompleted)给它,Observable会以通常的方式调用它。但是forEachFuture
自己返回一个Future
并且在get()
方法处阻塞,直到原始Observable执行完成,然后它返回,完成还是错误依赖于原始Observable是完成还是错误。
如果你想要一个函数阻塞直到Observable执行完成,可以使用这个操作符。
runAsync
rxjava-async
模块还包含一个runAsync
操作符。它很特殊,返回一个叫做StoppableObservable
的特殊Observable。
传递一个Action
和一个Scheduler
给runAsync
,它返回一个使用这个Action
产生数据的StoppableObservable
。这个Action
接受一个Observable
和一个Subscription
作为参数,它使用Subscription
检查unsubscribed
条件,一旦发现条件为真就立即停止发射数据。在任何时候你都可以使用unsubscribe
方法手动停止一个StoppableObservable
(这会同时取消订阅与这个StoppableObservable
关联的Subscription
)。
由于runAsync
会立即调用Action
并开始发射数据,在你创建StoppableObservable之后到你的观察者准备好接受数据之前这段时间里,可能会有一部分数据会丢失。如果这不符合你的要求,可以使用runAsync
的一个变体,它也接受一个Subject
参数,传递一个ReplaySubject
给它,你可以获取其它丢失的数据了。
在RxJava中还有一个版本的From
操作符可以将Future转换为Observable,与start
相似。
Timer
创建一个Observable,它在一个给定的延迟后发射一个特殊的值。
Timer
操作符创建一个在给定的时间段之后返回一个特殊值的Observable。
RxJava将这个操作符实现为timer
函数。
timer
返回一个Observable,它在延迟一段给定的时间后发射一个简单的数字0。
timer
操作符默认在computation
调度器上执行。有一个变体可以通过可选参数指定Scheduler。
- Javadoc: timer(long,TimeUnit)
- Javadoc: timer(long,TimeUnit,Scheduler)
变换操作
这个页面展示了可用于对Observable发射的数据执行变换操作的各种操作符。
- map( ) — 对序列的每一项都应用一个函数来变换Observable发射的数据序列
- flatMap( ), concatMap( ), and flatMapIterable( ) — 将Observable发射的数据集合变换为Observables集合,然后将这些Observable发射的数据平坦化的放进一个单独的Observable
- switchMap( ) — 将Observable发射的数据集合变换为Observables集合,然后只发射这些Observables最近发射的数据
- scan( ) — 对Observable发射的每一项数据应用一个函数,然后按顺序依次发射每一个值
- groupBy( ) — 将Observable分拆为Observable集合,将原始Observable发射的数据按Key分组,每一个Observable发射一组不同的数据
- buffer( ) — 它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个
- window( ) — 定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项
- cast( ) — 在发射之前强制将Observable发射的所有数据转换为指定类型
Buffer
定期收集Observable的数据放进一个数据包裹,然后发射这些数据包裹,而不是一次发射一个值。
Buffer
操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生的Observable发射这些数据的缓存集合。Buffer
操作符在很多语言特定的实现中有很多种变体,它们在如何缓存这个问题上存在区别。
注意:如果原来的Observable发射了一个onError
通知,Buffer
会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。
Window
操作符与Buffer
类似,但是它在发射之前把收集到的数据放进单独的Observable,而不是放进一个数据结构。
在RxJava中有许多Buffer
的变体:
buffer(count)
buffer(count)
以列表(List)的形式发射非重叠的缓存,每一个缓存至多包含来自原始Observable的count项数据(最后发射的列表数据可能少于count项)
- Javadoc: buffer(int)
buffer(count, skip)
buffer(count, skip)
从原始Observable的第一项数据开始创建新的缓存,此后每当收到skip
项数据,用count
项数据填充缓存:开头的一项和后续的count-1
项,它以列表(List)的形式发射缓存,取决于count
和skip
的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。
- Javadoc: buffer(int,int)
buffer(bufferClosingSelector)
当它订阅原来的Observable时,buffer(bufferClosingSelector)
开始将数据收集到一个List
,然后它调用bufferClosingSelector
生成第二个Observable,当第二个Observable发射一个TClosing
时,buffer
发射当前的List
,然后重复这个过程:开始组装一个新的List
,然后调用bufferClosingSelector
创建一个新的Observable并监视它。它会一直这样做直到原来的Observable执行完成。
- Javadoc: buffer(Func0)
buffer(boundary)
buffer(boundary)
监视一个名叫boundary
的Observable,每当这个Observable发射了一个值,它就创建一个新的List
开始收集来自原始Observable的数据并发射原来的List
。
- Javadoc: buffer(Observable)
- Javadoc: buffer(Observable,int)
buffer(bufferOpenings, bufferClosingSelector)
buffer(bufferOpenings, bufferClosingSelector)
监视这个叫bufferOpenings
的Observable(它发射BufferOpening
对象),每当bufferOpenings
发射了一个数据时,它就创建一个新的List
开始收集原始Observable的数据,并将bufferOpenings
传递给closingSelector
函数。这个函数返回一个Observable。buffer
监视这个Observable,当它检测到一个来自这个Observable的数据时,就关闭List
并且发射它自己的数据(之前的那个List)。
- Javadoc: buffer(Observable,Func1)
buffer(timespan, unit[, scheduler])
buffer(timespan, unit)
定期以List
的形式发射新的数据,每个时间段,收集来自原始Observable的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的Observale之后开始)。还有另一个版本的buffer
接受一个Scheduler
参数,默认情况下会使用computation
调度器。
- Javadoc: buffer(long,TimeUnit)
- Javadoc: buffer(long,TimeUnit,Scheduler)
buffer(timespan, unit, count[, scheduler])
每当收到来自原始Observable的count项数据,或者每过了一段指定的时间后,buffer(timespan, unit, count)
就以List
的形式发射这期间的数据,即使数据项少于count项。还有另一个版本的buffer
接受一个Scheduler
参数,默认情况下会使用computation
调度器。
- Javadoc: buffer(long,TimeUnit,int)
- Javadoc: buffer(long,TimeUnit,int,Scheduler)
buffer(timespan, timeshift, unit[, scheduler])
buffer(timespan, timeshift, unit)
在每一个timeshift
时期内都创建一个新的List
,然后用原始Observable发射的每一项数据填充这个列表(在把这个List
当做自己的数据发射前,从创建时开始,直到过了timespan
这么长的时间)。如果timespan
长于timeshift
,它发射的数据包将会重叠,因此可能包含重复的数据项。
还有另一个版本的buffer
接受一个Scheduler
参数,默认情况下会使用computation
调度器。
- Javadoc: buffer(long,long,TimeUnit)
- Javadoc: buffer(long,long,TimeUnit,Scheduler)
buffer-backpressure
你可以使用Buffer
操作符实现反压backpressure
(意思是,处理这样一个Observable:它产生数据的速度可能比它的观察者消费数据的速度快)。
Buffer操作符可以将大量的数据序列缩减为较少的数据缓存序列,让它们更容易处理。例如,你可以按固定的时间间隔,定期关闭和发射来自一个爆发性Observable的数据缓存。这相当于一个缓冲区。
示例代码
Observable> burstyBuffered = bursty.buffer(500, TimeUnit.MILLISECONDS);
或者,如果你想更进一步,可以在爆发期将数据收集到缓存,然后在爆发期终止时发射这些数据,使用 Debounce
操作符给buffer
操作符发射一个缓存关闭指示器(buffer closing indicator
)可以做到这一点。
代码示例:
// we have to multicast the original bursty Observable so we can use it
// both as our source and as the source for our buffer closing selector:
Observable burstyMulticast = bursty.publish().refCount();
// burstyDebounced will be our buffer closing selector:
Observable burstyDebounced = burstyMulticast.debounce(10, TimeUnit.MILLISECONDS);
// and this, finally, is the Observable of buffers we're interested in:
Observable> burstyBuffered = burstyMulticast.buffer(burstyDebounced);
参见
FlatMap
FlatMap
将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable
FlatMap
操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap
合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。
这个方法是很有用的,例如,当你有一个这样的Observable:它发射一个数据序列,这些数据本身包含Observable成员或者可以变换为Observable,因此你可以创建一个新的Observable发射这些次级Observable发射的数据的完整集合。
注意:FlatMap
对这些Observables发射的数据做的是合并(merge
)操作,因此它们可能是交错的。
在许多语言特定的实现中,还有一个操作符不会让变换后的Observables发射的数据交错,它按照严格的顺序发射这些数据,这个操作符通常被叫作ConcatMap
或者类似的名字。
RxJava将这个操作符实现为flatMap
函数。
注意:如果任何一个通过这个flatMap
操作产生的单独的Observable调用onError
异常终止了,这个Observable自身会立即调用onError
并终止。
这个操作符有一个接受额外的int
参数的一个变体。这个参数设置flatMap
从原来的Observable映射Observables的最大同时订阅数。当达到这个限制时,它会等待其中一个终止然后再订阅另一个。
- Javadoc: flatMap(Func1)
- Javadoc: flatMap(Func1,int)
还有一个版本的flatMap
为原始Observable的每一项数据和每一个通知创建一个新的Observable(并对数据平坦化)。
它也有一个接受额外int
参数的变体。
- Javadoc: flatMap(Func1,Func1,Func0)
- Javadoc: flatMap(Func1,Func1,Func0,int)
[图片上传失败...(image-5ffcff-1572186452759)]
还有一个版本的flatMap
会使用原始Observable的数据触发的Observable组合这些数据,然后发射这些数据组合。它也有一个接受额外int
参数的版本。
- Javadoc: flatMap(Func1,Func2)
- Javadoc: flatMap(Func1,Func2,int)
flatMapIterable
flatMapIterable
这个变体成对的打包数据,然后生成Iterable而不是原始数据和生成的Observables,但是处理方式是相同的。
- Javadoc: flatMapIterable(Func1)
- Javadoc: flatMapIterable(Func1,Func2)
concatMap
还有一个concatMap
操作符,它类似于最简单版本的flatMap
,但是它按次序连接而不是合并那些生成的Observables,然后产生自己的数据序列。
- Javadoc: concatMap(Func1)
switchMap
RxJava还实现了switchMap
操作符。它和flatMap
很像,除了一点:当原始Observable发射一个新的数据(Observable)时,它将取消订阅并停止监视产生执之前那个数据的Observable,只监视当前这一个。
- Javadoc: switchMap(Func1)
split
在特殊的StringObservable
类(默认没有包含在RxJava中)中还有一个split
操作符。它将一个发射字符串的Observable转换为另一个发射字符串的Observable,只不过,后者将原始的数据序列当做一个数据流,使用一个正则表达式边界分割它们,然后合并发射分割的结果。
GroupBy
将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个子序列
GroupBy
操作符将原始Observable分拆为一些Observables集合,它们中的每一个发射原始Observable数据序列的一个子序列。哪个数据项由哪一个Observable发射是由一个函数判定的,这个函数给每一项指定一个Key,Key相同的数据会被同一个Observable发射。
RxJava实现了groupBy
操作符。它返回Observable的一个特殊子类GroupedObservable
,实现了GroupedObservable
接口的对象有一个额外的方法getKey
,这个Key用于将数据分组到指定的Observable。
有一个版本的groupBy
允许你传递一个变换函数,这样它可以在发射结果GroupedObservable
之前改变数据项。
注意:groupBy
将原始Observable分解为一个发射多个GroupedObservable
的Observable,一旦有订阅,每个GroupedObservable
就开始缓存数据。因此,如果你忽略这些GroupedObservable
中的任何一个,这个缓存可能形成一个潜在的内存泄露。因此,如果你不想观察,也不要忽略GroupedObservable
。你应该使用像take(0)
这样会丢弃自己的缓存的操作符。
如果你取消订阅一个GroupedObservable
,那个Observable将会终止。如果之后原始的Observable又发射了一个与这个Observable的Key匹配的数据,groupBy
将会为这个Key创建一个新的GroupedObservable
。
groupBy
默认不在任何特定的调度器上执行。
- Javadoc: groupBy(Func1)
- Javadoc: groupBy(Func1,Func1)
Map
对Observable发射的每一项数据应用一个函数,执行变换操作
Map
操作符对原始Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable。
RxJava将这个操作符实现为map
函数。这个操作符默认不在任何特定的调度器上执行。
- Javadoc: map(Func1)
cast
cast
操作符将原始Observable发射的每一项数据都强制转换为一个指定的类型,然后再发射数据,它是map
的一个特殊版本。
- Javadoc: cast(Class)
encode
encode
在StringObservable
类中,不是标准RxJava的一部分,它也是一个特殊的map
操作符。encode
将一个发射字符串的Observable变换为一个发射字节数组(这个字节数组按照原始字符串中的多字节字符边界划分)的Observable。
byLine
byLine
同样在StringObservable
类中,也不是标准RxJava的一部分,它也是一个特殊的map
操作符。byLine
将一个发射字符串的Observable变换为一个按行发射来自原始Observable的字符串的Observable。
Scan
连续地对数据序列的每一项应用一个函数,然后连续发射结果
Scan
操作符对原始Observable发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。它持续进行这个过程来产生剩余的数据序列。这个操作符在某些情况下被叫做accumulator
。
RxJava实现了scan
操作符。
示例代码:
Observable.just(1, 2, 3, 4, 5)
.scan(new Func2() {
@Override
public Integer call(Integer sum, Integer item) {
return sum + item;
}
}).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: 6
Next: 10
Next: 15
Sequence complete.
- Javadoc: scan(Func2)
有一个scan
操作符的变体,你可以传递一个种子值给累加器函数的第一次调用(Observable发射的第一项数据)。如果你使用这个版本,scan
将发射种子值作为自己的第一项数据。注意:传递null
作为种子值与不传递是不同的,null
种子值是合法的。
- Javadoc: scan(R,Func2)
这个操作符默认不在任何特定的调度器上执行。
Window
定期将来自原始Observable的数据分解为一个Observable窗口,发射这些窗口,而不是每次发射一项数据
Window
和Buffer
类似,但不是发射来自原始Observable的数据包,它发射的是Observables,这些Observables中的每一个都发射原始Observable数据的一个子集,最后发射一个onCompleted
通知。
和Buffer
一样,Window
有很多变体,每一种都以自己的方式将原始Observable分解为多个作为结果的Observable,每一个都包含一个映射原始数据的window
。用Window
操作符的术语描述就是,当一个窗口打开(when a window "opens")意味着一个新的Observable已经发射(产生)了,而且这个Observable开始发射来自原始Observable的数据;当一个窗口关闭(when a window "closes")意味着发射(产生)的Observable停止发射原始Observable的数据,并且发射终止通知onCompleted
给它的观察者们。
在RxJava中有许多种Window
操作符的变体。
window(closingSelector)
window
的这个变体会立即打开它的第一个窗口。每当它观察到closingSelector
返回的Observable发射了一个对象时,它就关闭当前打开的窗口并立即打开一个新窗口。用这个方法,这种window
变体发射一系列不重叠的窗口,这些窗口的数据集合与原始Observable发射的数据是一一对应的。
- Javadoc: window(Func0)
window(windowOpenings, closingSelector)
无论何时,只要window
观察到windowOpenings
这个Observable发射了一个Opening
对象,它就打开一个窗口,并且同时调用closingSelector
生成一个与那个窗口关联的关闭(closing)Observable。当这个关闭(closing)Observable发射了一个对象时,window
操作符就会关闭那个窗口。对这个变体来说,由于当前窗口的关闭和新窗口的打开是由单独的Observable管理的,它创建的窗口可能会存在重叠(重复某些来自原始Observable的数据)或间隙(丢弃某些来自原始Observable的数据)。
- Javadoc: window(Observable,Func1)
window(count)
这个window
的变体立即打开它的第一个窗口。每当当前窗口发射了count
项数据,它就关闭当前窗口并打开一个新窗口。如果从原始Observable收到了onError
或onCompleted
通知它也会关闭当前窗口。这种window
变体发射一系列不重叠的窗口,这些窗口的数据集合与原始Observable发射的数据是一一对应的。
- Javadoc: window(int)
window(count, skip)
这个window
的变体立即打开它的第一个窗口。原始Observable每发射skip
项数据它就打开一个新窗口(例如,如果skip
等于3,每到第三项数据,它会打开一耳光新窗口)。每当当前窗口发射了count
项数据,它就关闭当前窗口并打开一个新窗口。如果从原始Observable收到了onError
或onCompleted
通知它也会关闭当前窗口。如果skip=count
,它的行为与window(source, count)
相同;如果skip < count
,窗口可会有count - skip
个重叠的数据;如果skip > count
,在两个窗口之间会有skip - count
项数据被丢弃。
- Javadoc: window(int,int)
window(timespan, unit[, scheduler])
这个window
的变体立即打开它的第一个窗口。每当过了timespan
这么长的时间它就关闭当前窗口并打开一个新窗口(时间单位是unit
,可选在调度器scheduler
上执行)。如果从原始Observable收到了onError
或onCompleted
通知它也会关闭当前窗口。这种window
变体发射一系列不重叠的窗口,这些窗口的数据集合与原始Observable发射的数据也是一一对应的。
- Javadoc: window(long,TimeUnit)
- Javadoc: window(long,TimeUnit,Scheduler)
window(timespan, unit, count[, scheduler])
这个window
的变体立即打开它的第一个窗口。这个变体是window(count)
和window(timespan, unit[, scheduler])
的结合,每当过了timespan
的时长或者当前窗口收到了count
项数据,它就关闭当前窗口并打开另一个。如果从原始Observable收到了onError
或onCompleted
通知它也会关闭当前窗口。这种window
变体发射一系列不重叠的窗口,这些窗口的数据集合与原始Observable发射的数据也是一一对应的。
- Javadoc: window(long,TimeUnit,int)
- Javadoc: window(long,TimeUnit,int,Scheduler)
window(timespan, timeshift, unit[, scheduler])
buffer(timespan, timeshift, unit)
在每一个timeshift
时期内都创建一个新的List
,然后用原始Observable发射的每一项数据填充这个列表(在把这个List
当做自己的数据发射前,从创建时开始,直到过了timespan
这么长的时间)。如果timespan
长于timeshift
,它发射的数据包将会重叠,因此可能包含重复的数据项。
这个window
的变体立即打开它的第一个窗口。随后每当过了timeshift
的时长就打开一个新窗口(时间单位是unit
,可选在调度器scheduler
上执行),当窗口打开的时长达到timespan
,它就关闭当前打开的窗口。如果从原始Observable收到了onError
或onCompleted
通知它也会关闭当前窗口。窗口的数据可能重叠也可能有间隙,取决于你设置的timeshift
和timespan
的值。
这个变体的window
默认在computation
调度器上执行它的定时器。
- Javadoc: window(long,long,TimeUnit)
- Javadoc: window(long,long,TimeUnit,Scheduler)
window-backpressure
你可以使用Window
操作符实现反压backpressure
(意思是,处理这样一个Observable:它产生数据的数据可能比它的观察者消费数据的数据快)。
Window操作符可以将大量的数据序列缩减为较少的数据窗口序列,让它们更容易处理。例如,你可以按固定的时间间隔,定期关闭和发射来自一个爆发性Observable的数据窗口。
示例代码
Observable> burstyWindowed = bursty.window(500, TimeUnit.MILLISECONDS);
你还可以选择每当收到爆发性Observable的N项数据时发射一个新的数据窗口。
示例代码
Observable> burstyWindowed = bursty.window(5);
过滤操作
这个页面展示的操作符可用于过滤和选择Observable发射的数据序列。
- filter( ) — 过滤数据
- takeLast( ) — 只发射最后的N项数据
- last( ) — 只发射最后的一项数据
- lastOrDefault( ) — 只发射最后的一项数据,如果Observable为空就发射默认值
- takeLastBuffer( ) — 将最后的N项数据当做单个数据发射
- skip( ) — 跳过开始的N项数据
- skipLast( ) — 跳过最后的N项数据
- take( ) — 只发射开始的N项数据
- first( ) and takeFirst( ) — 只发射第一项数据,或者满足某种条件的第一项数据
- firstOrDefault( ) — 只发射第一项数据,如果Observable为空就发射默认值
- elementAt( ) — 发射第N项数据
- elementAtOrDefault( ) — 发射第N项数据,如果Observable数据少于N项就发射默认值
- sample( ) or throttleLast( ) — 定期发射Observable最近的数据
- throttleFirst( ) — 定期发射Observable发射的第一项数据
- throttleWithTimeout( ) or debounce( ) — 只有当Observable在指定的时间后还没有发射数据时,才发射一个数据
- timeout( ) — 如果在一个指定的时间段后还没发射数据,就发射一个异常
- distinct( ) — 过滤掉重复数据
- distinctUntilChanged( ) — 过滤掉连续重复的数据
- ofType( ) — 只发射指定类型的数据
- ignoreElements( ) — 丢弃所有的正常数据,只发射错误或完成通知
Debounce
仅在过了一段指定的时间还没发射数据时才发射一个数据
Debounce
操作符会过滤掉发射速率过快的数据项。
RxJava将这个操作符实现为throttleWithTimeout
和debounce
。
注意:这个操作符会会接着最后一项数据发射原始Observable的onCompleted
通知,即使这个通知发生在你指定的时间窗口内(从最后一项数据的发射算起)。也就是说,onCompleted
通知不会触发限流。
throttleWithTimeout
throtleWithTimeout/debounce
的一个变体根据你指定的时间间隔进行限流,时间单位通过TimeUnit
参数指定。
这种操作符默认在computation
调度器上执行,但是你可以通过第三个参数指定。
- Javadoc: throttleWithTimeout(long,TimeUnit) and debounce(long,TimeUnit)
- Javadoc: throttleWithTimeout(long,TimeUnit,Scheduler) and debounce(long,TimeUnit,Scheduler)
debounce
debounce
操作符的一个变体通过对原始Observable的每一项应用一个函数进行限流,这个函数返回一个Observable。如果原始Observable在这个新生成的Observable终止之前发射了另一个数据,debounce
会抑制(suppress)这个数据项。
debounce
的这个变体默认不在任何特定的调度器上执行。
Rxjava操作符四