下面是常用的操作符列表:
- 创建操作 Create, Defer, Empty/Never/Throw, From, Interval, Just, Range, Repeat, Start, Timer
- 变换操作 Buffer, FlatMap, GroupBy, Map, Scan和Window
- 过滤操作 Debounce, Distinct, ElementAt, Filter, First, IgnoreElements, Last, Sample, Skip, SkipLast, Take, TakeLast
- 组合操作 And/Then/When, CombineLatest, Join, Merge, StartWith, Switch, Zip
- 错误处理 Catch和Retry
- 辅助操作 Delay, Do, Materialize/Dematerialize, ObserveOn, Serialize, Subscribe, SubscribeOn, TimeInterval, Timeout, Timestamp, Using
- 条件和布尔操作 All, Amb, Contains, DefaultIfEmpty, SequenceEqual, SkipUntil, SkipWhile, TakeUntil, TakeWhile
- 算术和集合操作 Average, Concat, Count, Max, Min, Reduce, Sum
- 转换操作 To
- 连接操作 Connect, Publish, RefCount, Replay
- 反压操作,用于增加特殊的流程控制策略的操作符
这些操作符并不全都是ReactiveX的核心组成部分,有一些是语言特定的实现或可选的模块。
RxJava
在RxJava中,一个实现了Observer接口的对象可以订阅(subscribe)一个Observable 类的实例。订阅者(subscriber)对Observable发射(emit)的任何数据或数据序列作出响应。这种模式简化了并发操作,因为它不需要阻塞等待Observable发射数据,而是创建了一个处于待命状态的观察者哨兵,哨兵在未来某个时刻响应Observable的通知。
Single
介绍
RxJava(以及它派生出来的RxGroovy和RxScala)中有一个名为Single的Observable变种。
Single类似于Observable,不同的是,它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。
因此,不同于Observable需要三个方法onNext, onError, onCompleted,订阅Single只需要两个方法:
- onSuccess - Single发射单个的值到这个方法
- onError - 如果无法发射需要的值,Single发射一个Throwable对象到这个方法
Single只会调用这两个方法中的一个,而且只会调用一次,调用了任何一个方法之后,订阅关系终止。
Single的操作符
Single也可以组合使用多种操作,一些操作符让你可以混合使用Observable和Single:
操作符 | 返回值 | 说明 |
---|---|---|
compose | Single | 创建一个自定义的操作符 |
concat and concatWith | Observable | 连接多个Single和Observable发射的数据 |
create | Single | 调用观察者的create方法创建一个Single |
error | Single | 返回一个立即给订阅者发射错误通知的Single |
flatMap | Single | 返回一个Single,它发射对原Single的数据执行flatMap操作后的结果 |
flatMapObservable | Observable | 返回一个Observable,它发射对原Single的数据执行flatMap操作后的结果 |
from | Single | 将Future转换成Single |
just | Single | 返回一个发射一个指定值的Single |
map | Single | 返回一个Single,它发射对原Single的数据执行map操作后的结果 |
merge | Single | 将一个Single(它发射的数据是另一个Single,假设为B)转换成另一个Single(它发射来自另一个Single(B)的数据) |
merge and mergeWith | Observable | 合并发射来自多个Single的数据 |
observeOn | Single | 指示Single在指定的调度程序上调用订阅者的方法 |
onErrorReturn | Single | 将一个发射错误通知的Single转换成一个发射指定数据项的Single |
subscribeOn | Single | 指示Single在指定的调度程序上执行操作 |
timeout | Single | 它给原有的Single添加超时控制,如果超时了就发射一个错误通知 |
toSingle | Single | 将一个发射单个值的Observable转换为一个Single |
zip and zipWith | Single | 将多个Single转换为一个,后者发射的数据是对前者应用一个函数后的结果 |
操作符图示
详细的图解可以参考英文文档:Single
Subject
Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中(如RxJava),它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。
由于一个Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是"冷"的--就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个"冷"的Observable变成"热"的。
Subject的种类
针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在,而且一些实现使用其它的命名约定(例如,在RxScala中Subject被称作PublishSubject)。
AsyncSubject
一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。(如果原始Observable没有发射任何值,AsyncObject也不发射任何值)它会把这最后一个值发射给任何后续的观察者。 然而,如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。BehaviorSubject
当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。 然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。PublishSubject
PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据(除非你可以阻止它发生),因此这里有一个风险:在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。如果要确保来自原始Observable的所有数据都被分发,你需要这样做:或者使用Create创建那个Observable以便手动给它引入"冷"Observable的行为(当所有观察者都已经订阅时才开始发射数据),或者改用ReplaySubject。 如果原始的Observable因为发生了一个错误而终止,PublishSubject将不会发射任何数据,只是简单的向前传递这个错误通知。ReplaySubject
ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。也有其它版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据(原始Observable发射的)。
如果你把ReplaySubject当作一个观察者使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。
RxJava的对应类
假设你有一个Subject,你想把它传递给其它的代理或者暴露它的Subscriber接口,你可以调用它的asObservable方法,这个方法返回一个Observable。具体使用方法可以参考Javadoc文档。
串行化
如果你把 Subject
当作一个 Subscriber
使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。
要避免此类问题,你可以将 Subject
转换为一个 SerializedSubject
,类似于这样:
mySafeSubject = new SerializedSubject( myUnsafeSubject );
调度器 Scheduler
如果你想给Observable操作符链添加多线程功能,你可以指定操作符(或者特定的Observable)在特定的调度器(Scheduler)上执行。
某些ReactiveX的Observable操作符有一些变体,它们可以接受一个Scheduler参数。这个参数指定操作符将它们的部分或全部任务放在一个特定的调度器上执行。
使用ObserveOn和SubscribeOn操作符,你可以让Observable在一个特定的调度器上执行,ObserveOn指示一个Observable在一个特定的调度器上调用观察者的onNext, onError和onCompleted方法,SubscribeOn更进一步,它指示Observable将全部的处理过程(包括发射数据和通知)放在特定的调度器上执行。
RxJava示例
调度器的种类
下表展示了RxJava中可用的调度器种类:
调度器类型 | 效果 |
---|---|
Schedulers.computation( ) | 用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量 |
Schedulers.from(executor) | 使用指定的Executor作为调度器 |
Schedulers.immediate( ) | 在当前线程立即开始执行任务 |
Schedulers.io( ) | 用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器 |
Schedulers.newThread( ) | 为每个任务创建一个新线程 |
Schedulers.trampoline( ) | 当其它排队的任务完成后,在当前线程排队开始执行 |
默认调度器
在RxJava中,某些Observable操作符的变体允许你设置用于操作执行的调度器,其它的则不在任何特定的调度器上执行,或者在一个指定的默认调度器上执行。下面的表格个列出了一些操作符的默认调度器:
操作符 | 调度器 |
---|---|
buffer(timespan) | computation |
buffer(timespan, count) | computation |
buffer(timespan, timeshift) | computation |
debounce(timeout, unit) | computation |
delay(delay, unit) | computation |
delaySubscription(delay, unit) | computation |
interval | computation |
repeat | trampoline |
replay(time, unit) | computation |
replay(buffersize, time, unit) | computation |
replay(selector, time, unit) | computation |
replay(selector, buffersize, time, unit) | computation |
retry | trampoline |
sample(period, unit) | computation |
skip(time, unit) | computation |
skipLast(time, unit) | computation |
take(time, unit) | computation |
takeLast(time, unit) | computation |
takeLast(count, time, unit) | computation |
takeLastBuffer(time, unit) | computation |
takeLastBuffer(count, time, unit) | computation |
throttleFirst | computation |
throttleLast | computation |
throttleWithTimeout | computation |
timeInterval | immediate |
timeout(timeoutSelector) | immediate |
timeout(firstTimeoutSelector, timeoutSelector) | immediate |
timeout(timeoutSelector, other) | immediate |
timeout(timeout, timeUnit) | computation |
timeout(firstTimeoutSelector, timeoutSelector, other) | immediate |
timeout(timeout, timeUnit, other) | computation |
timer | computation |
timestamp | immediate |
window(timespan) | computation |
window(timespan, count) | computation |
window(timespan, timeshift) | computation |
使用调度器
除了将这些调度器传递给RxJava的Observable操作符,你也可以用它们调度你自己的任务。下面的示例展示了Scheduler.Worker的用法:
worker = Schedulers.newThread().createWorker();
worker.schedule(new Action0() {
@Override
public void call() {
yourWork();
}
});
// some time later...
worker.unsubscribe();
递归调度器
要调度递归的方法调用,你可以使用schedule,然后再用schedule(this),示例:
worker = Schedulers.newThread().createWorker();
worker.schedule(new Action0() {
@Override
public void call() {
yourWork();
// recurse until unsubscribed (schedule will do nothing if unsubscribed)
worker.schedule(this);
}
});
// some time later...
worker.unsubscribe();
检查或设置取消订阅状态
Worker类的对象实现了Subscription接口,使用它的isUnsubscribed和unsubscribe方法,所以你可以在订阅取消时停止任务,或者从正在调度的任务内部取消订阅,示例:
Worker worker = Schedulers.newThread().createWorker();
Subscription mySubscription = worker.schedule(new Action0() {
@Override
public void call() {
while(!worker.isUnsubscribed()) {
status = yourWork();
if(QUIT == status) { worker.unsubscribe(); }
}
}
});
Worker同时是Subscription,因此你可以(通常也应该)调用它的unsubscribe方法通知可以挂起任务和释放资源了。
延时和周期调度器
你可以使用schedule(action,delayTime,timeUnit)在指定的调度器上延时执行你的任务,下面例子中的任务将在500毫秒之后开始执行:
someScheduler.schedule(someAction, 500, TimeUnit.MILLISECONDS);
使用另一个版本的schedule,schedulePeriodically(action,initialDelay,period,timeUnit)方法让你可以安排一个定期执行的任务,下面例子的任务将在500毫秒之后执行,然后每250毫秒执行一次:
someScheduler.schedulePeriodically(someAction, 500, 250, TimeUnit.MILLISECONDS);
测试调度器
TestScheduler让你可以对调度器的时钟表现进行手动微调。这对依赖精确时间安排的任务的测试很有用处。这个调度器有三个额外的方法:
- advanceTimeTo(time,unit) 向前波动调度器的时钟到一个指定的时间点
- advanceTimeBy(time,unit) 将调度器的时钟向前拨动一个指定的时间段
- triggerActions( ) 开始执行任何计划中的但是未启动的任务,如果它们的计划时间等于或者早于调度器时钟的当前时间
操作符分类
ReactiveX的每种编程语言的实现都实现了一组操作符的集合。不同的实现之间有很多重叠的部分,也有一些操作符只存在特定的实现中。每种实现都倾向于用那种编程语言中他们熟悉的上下文中相似的方法给这些操作符命名。
本文首先会给出ReactiveX的核心操作符列表和对应的文档链接,后面还有一个决策树用于帮助你根据具体的场景选择合适的操作符。最后有一个语言特定实现的按字母排序的操作符列表。
如果你想实现你自己的操作符,可以参考这里:实现自定义操作符
创建操作
用于创建Observable的操作符
-
Create
— 通过调用观察者的方法从头创建一个Observable -
Defer
— 在观察者订阅之前不创建这个Observable,为每一个观察者创建一个新的Observable -
Empty/Never/Throw
— 创建行为受限的特殊Observable -
From
— 将其它的对象或数据结构转换为Observable -
Interval
— 创建一个定时发射整数序列的Observable -
Just
— 将对象或者对象集合转换为一个会发射这些对象的Observable -
Range
— 创建发射指定范围的整数序列的Observable -
Repeat
— 创建重复发射特定的数据或数据序列的Observable -
Start
— 创建发射一个函数的返回值的Observable -
Timer
— 创建在一个指定的延迟之后发射单个数据的Observable
变换操作
这些操作符可用于对Observable发射的数据进行变换,详细解释可以看每个操作符的文档
-
Buffer
— 缓存,可以简单的理解为缓存,它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个 -
FlatMap
— 扁平映射,将Observable发射的数据变换为Observables集合,然后将这些Observable发射的数据平坦化的放进一个单独的Observable,可以认为是一个将嵌套的数据结构展开的过程。 -
GroupBy
— 分组,将原来的Observable分拆为Observable集合,将原始Observable发射的数据按Key分组,每一个Observable发射一组不同的数据 -
Map
— 映射,通过对序列的每一项都应用一个函数变换Observable发射的数据,实质是对序列中的每一项执行一个函数,函数的参数就是这个数据项 -
Scan
— 扫描,对Observable发射的每一项数据应用一个函数,然后按顺序依次发射这些值 -
Window
— 窗口,定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项。类似于Buffer,但Buffer发射的是数据,Window发射的是Observable,每一个Observable发射原始Observable的数据的一个子集
过滤操作
这些操作符用于从Observable发射的数据中进行选择
-
Debounce
— 只有在空闲了一段时间后才发射数据,通俗的说,就是如果一段时间没有操作,就执行一次操作 -
Distinct
— 去重,过滤掉重复数据项 -
ElementAt
— 取值,取特定位置的数据项 -
Filter
— 过滤,过滤掉没有通过谓词测试的数据项,只发射通过测试的 -
First
— 首项,只发射满足条件的第一条数据 -
IgnoreElements
— 忽略所有的数据,只保留终止通知(onError或onCompleted) -
Last
— 末项,只发射最后一条数据 -
Sample
— 取样,定期发射最新的数据,等于是数据抽样,有的实现里叫ThrottleFirst -
Skip
— 跳过前面的若干项数据 -
SkipLast
— 跳过后面的若干项数据 -
Take
— 只保留前面的若干项数据 -
TakeLast
— 只保留后面的若干项数据
组合操作
组合操作符用于将多个Observable组合成一个单一的Observable
-
And/Then/When
— 通过模式(And条件)和计划(Then次序)组合两个或多个Observable发射的数据集 -
CombineLatest
— 当两个Observables中的任何一个发射了一个数据时,通过一个指定的函数组合每个Observable发射的最新数据(一共两个数据),然后发射这个函数的结果 -
Join
— 无论何时,如果一个Observable发射了一个数据项,只要在另一个Observable发射的数据项定义的时间窗口内,就将两个Observable发射的数据合并发射 -
Merge
— 将两个Observable发射的数据组合并成一个 -
StartWith
— 在发射原来的Observable的数据序列之前,先发射一个指定的数据序列或数据项 -
Switch
— 将一个发射Observable序列的Observable转换为这样一个Observable:它逐个发射那些Observable最近发射的数据 -
Zip
— 打包,使用一个指定的函数将多个Observable发射的数据组合在一起,然后将这个函数的结果作为单项数据发射
错误处理
这些操作符用于从错误通知中恢复
-
Catch
— 捕获,继续序列操作,将错误替换为正常的数据,从onError通知中恢复 -
Retry
— 重试,如果Observable发射了一个错误通知,重新订阅它,期待它正常终止
辅助操作
一组用于处理Observable的操作符
-
Delay
— 延迟一段时间发射结果数据 -
Do
— 注册一个动作占用一些Observable的生命周期事件,相当于Mock某个操作 -
Materialize/Dematerialize
— 将发射的数据和通知都当做数据发射,或者反过来 -
ObserveOn
— 指定观察者观察Observable的调度程序(工作线程) -
Serialize
— 强制Observable按次序发射数据并且功能是有效的 -
Subscribe
— 收到Observable发射的数据和通知后执行的操作 -
SubscribeOn
— 指定Observable应该在哪个调度程序上执行 -
TimeInterval
— 将一个Observable转换为发射两个数据之间所耗费时间的Observable -
Timeout
— 添加超时机制,如果过了指定的一段时间没有发射数据,就发射一个错误通知 -
Timestamp
— 给Observable发射的每个数据项添加一个时间戳 -
Using
— 创建一个只在Observable的生命周期内存在的一次性资源
条件和布尔操作
这些操作符可用于单个或多个数据项,也可用于Observable
-
All
— 判断Observable发射的所有的数据项是否都满足某个条件 -
Amb
— 给定多个Observable,只让第一个发射数据的Observable发射全部数据 -
Contains
— 判断Observable是否会发射一个指定的数据项 -
DefaultIfEmpty
— 发射来自原始Observable的数据,如果原始Observable没有发射数据,就发射一个默认数据 -
SequenceEqual
— 判断两个Observable是否按相同的数据序列 -
SkipUntil
— 丢弃原始Observable发射的数据,直到第二个Observable发射了一个数据,然后发射原始Observable的剩余数据 -
SkipWhile
— 丢弃原始Observable发射的数据,直到一个特定的条件为假,然后发射原始Observable剩余的数据 -
TakeUntil
— 发射来自原始Observable的数据,直到第二个Observable发射了一个数据或一个通知 -
TakeWhile
— 发射原始Observable的数据,直到一个特定的条件为真,然后跳过剩余的数据
算术和聚合操作
这些操作符可用于整个数据序列
-
Average
— 计算Observable发射的数据序列的平均值,然后发射这个结果 -
Concat
— 不交错的连接多个Observable的数据 -
Count
— 计算Observable发射的数据个数,然后发射这个结果 -
Max
— 计算并发射数据序列的最大值 -
Min
— 计算并发射数据序列的最小值 -
Reduce
— 按顺序对数据序列的每一个应用某个函数,然后返回这个值 -
Sum
— 计算并发射数据序列的和
连接操作
一些有精确可控的订阅行为的特殊Observable
-
Connect
— 指示一个可连接的Observable开始发射数据给订阅者 -
Publish
— 将一个普通的Observable转换为可连接的 -
RefCount
— 使一个可连接的Observable表现得像一个普通的Observable -
Replay
— 确保所有的观察者收到同样的数据序列,即使他们在Observable开始发射数据之后才订阅
转换操作
-
To
— 将Observable转换为其它的对象或数据结构 -
Blocking
阻塞Observable的操作符
操作符决策树
几种主要的需求
- 直接创建一个Observable(创建操作)
- 组合多个Observable(组合操作)
- 对Observable发射的数据执行变换操作(变换操作)
- 从Observable发射的数据中取特定的值(过滤操作)
- 转发Observable的部分值(条件/布尔/过滤操作)
- 对Observable发射的数据序列求值(算术/聚合操作)
这个页面展示了创建Observable的各种方法。
- just( ) — 将一个或多个对象转换成发射这个或这些对象的一个Observable
- from( ) — 将一个Iterable, 一个Future, 或者一个数组转换成一个Observable
- repeat( ) — 创建一个重复发射指定数据或数据序列的Observable
- repeatWhen( ) — 创建一个重复发射指定数据或数据序列的Observable,它依赖于另一个Observable发射的数据
- create( ) — 使用一个函数从头创建一个Observable
- defer( ) — 只有当订阅者订阅才创建Observable;为每个订阅创建一个新的Observable
- range( ) — 创建一个发射指定范围的整数序列的Observable
- interval( ) — 创建一个按照给定的时间间隔发射整数序列的Observable
- timer( ) — 创建一个在给定的延时之后发射单个数据的Observable
- empty( ) — 创建一个什么都不做直接通知完成的Observable
- error( ) — 创建一个什么都不做直接通知错误的Observable
- never( ) — 创建一个不发射任何数据的Observable
创建操作
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
当你使用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执行完成,可以使用这个操作符。