官方文档链接:http://reactivex.io/documentation/single.html
1.前言
虽然知道了所有的操作符,但若是不明白在什么情况下使用,也是无济于事。在讲解新的被观察者之前,介绍一下官网提供的决策树,以方便大家在合适的地方使用适当的操作符。
2.操作符决策树
这个决策树可以帮助选择最适合当前用例的操作符。
- 想要创建新的被观察者
- 产生一个特定事件:Just
- 订阅时调用函数的返回值:Start
- 订阅时调用
Action
、Callable
、Runnable
等方法的返回值:From - 特定延迟之后:Timer
- 从特定
Array
、Iterable
等拉取事件:From - 从Future获取事件:Start
- 从Future获取事件队列:From
- 重复产生某事件队列:Repeat
- 使用自定义逻辑从头开始:Create
- 每个观察者订阅时都创建:Defer
- 产生一个整数序列:Range
- 彼此有特定的时间间隔:Interval
- 在特定延迟之后:Timer
- 彼此有特定的时间间隔:Interval
- 没产生事件就完成:Empty
- 没干一点事:Never
- 产生一个特定事件:Just
- 想要通过合并其它被观察者来创建一个被观察者
- 合并所有的被观察者产生的所有事件,不管接收到的顺序:Merge
- 合并所有的被观察者产生的所有事件,每次一个被观察者:Concat
- 通过合并两个以上的被观察者的事件,从而产生新的事件
- 每个被观察者都产生新的事件:Zip
- 任一被观察者产生新的事件:CombineLatest
- 一个被观察者产生的一个事件进入另一个被观察者产生的某事件定义的视窗:Join
- 通过Pattern和Plan的转换:And / Then / When
- 每个事件只来自于最近开始产生事件的被观察者:Switch
- 想要传递改变后的被观察者事件
- 通过函数每次改变一个:Map
- 传递相应的被观察者产生的所有事件:FlatMap
- 按照被观察者产生顺序,依次执行:ConcatMap
- 改变的过程基于之前的事件:Scan
- 通过给每个事件添加时间戳:Timestamp
- 替换为事件与之前事件的时间间隔的标识:TimeInterval
- 想要通过推迟时间改变被观察者产生的事件:Delay
- 想要将被观察者的事件和通知转换为事件进行传递
- 将事件和通知包裹进
Notification
对象:Materialize- 接着反转上面的过程:Dematerialize
- 将事件和通知包裹进
- 想要忽略被观察者产生的所有事件且只传递
onCompleted()
/onError()
通知:IgnoreElements - 想要保持被观察者,但在它事件队列前添加事件:StartWith
- 仅当它事件队列是空的:DefaultIfEmpty
- 想要收集被观察者的事件,以集合的方式传递事件:Buffer
- 只包含最后的事件:TakeLast
- 想要将一个被观察者划分成多个被观察者:Window
- 相似的事件最终分在同一个被观察者:GroupBy
- 想要获取被观察者产生的某特定事件
- 在被观察者完成之前产生的最后一个事件:Last
- 被观察者产生的唯一的事件:Single
- 被观察者产生的第一个事件:First
- 想要传递被观察者的某些事件
- 过滤出那些不匹配一定规则的事件:Filter
- 只最初的事件:First
- 只最初的n个事件:Take
- 只最后的事件:Last
- 只第n个事件:ElementAt
- 最初的n个事件之后的那些事件
- 忽略最初的n个事件:Skip
- 忽略所有,直到某个事件匹配规则:SkipWhile
- 忽略最初的一段时间内的事件:Skip
- 忽略所有,直到第二个被观察者产生了事件:SkipUntil
- 最后的n个事件之前的那些事件
- 忽略最后的n个事件:SkipLast
- 不忽略,直到某个事件匹配规则:TakeWhile
- 忽略被观察者完成之前一段时间内的事件:SkipLast
- 不忽略,直到第二个被观察者产生了事件:TakeUntil
- 周期性选取被观察者的事件:Sample
- 只传递那些特定时间段内没被其它事件追随的事件:Debounce
- 忽略那些与已经传递的事件一样的事件:Distinct
- 忽略那些与前一个事件一样的事件:DistinctUntilChanged
- 在被观察者开始产生事件之后一段时间,才订阅它:DelaySubscription
- 想要传递第一个产生事件的被观察者的事件:Amb
- 想要判断被观察者产生的整个事件队列
- 如果所有的事件通过某些测试,传递单一的布尔值标识:All
- 如果任一的事件通过某些测试,传递单一的布尔值标识:Contains
- 如果被观察者没产生事件,传递单一的布尔值标识:IsEmpty
- 如果事件队列与第二个被观察者产生的相同,传递单一的布尔值标识:SequenceEqual
- 传递所有事件值的平均值:Average
- 传递所有事件值的和:Sum
- 传递一个数字,标识队列中有多少事件:Count
- 传递拥有最大值的事件:Max
- 传递拥有最小值的事件:Min
- 轮流对每个事件应用累计函数,并传递结果:Scan
- 想要将被观察者产生的整个事件队列转换成某些其它数据结构:To
- 想要一个操作符执行于特定的线程:SubscribeOn
- 什么时候被观察者通知观察者:ObserveOn
- 想要一个被观察者在某些事件发生时,调用某个特定行为:Do
- 想要一个被观察者通知观察者
onError()
事件:Throw- 如果一个特定时间段内,被观察者没有产生一个事件:Timeout
- 想要一个被观察者优雅地恢复
- 当发生超时,切换到备用的被观察者:Timeout
- 上游产生
onError()
通知:Catch- 试图重新订阅上游的被观察者:Retry
- 想要创建一个与被观察者拥有相同生命周期的资源:Using
- 想要订阅一个被观察者,且接收一个阻塞直到被观察者完成的
Future
:Start - 想要一个被观察者开始不产生事件给订阅者直到被要求:Publish
- 接着只传递队列中最后一个事件:PublishLast
- 接着传递完整的队列,即使在开始产生事件队列之后订阅:Replay
- 一旦所有的订阅者取消订阅,自动不发事件:refCount
- 接着通知被观察者开始产生事件:Connect
参考的文章:
- Which Operator do I use? by Dennis Stoyanov (一个相似的关于RxJS操作符的决策树)
3.Single
RxJava(及其衍生物如RxGroovy和RxScala)已经发展出一种被观察者的变体,称为Single
。Single在某些方面像被观察者,但它总是产生一个值或一个onError()
通知,而不是产生一系列值。因为这个原因,只需要使用两个方法订阅Single,而不是往常响应被观察者通知的三个方法(onNext()
、onError()
和onCompleted()
):
onSuccess()
通过这个方法,Single产生唯一事件。
onError()
通过这个方法,发出导致Single无法产生事件的错误通知。
Single将只调用其中一个方法,且只调用它一次。不论调用哪个方法,Single终止且结束已在的订阅。
3.1.操作符概览
像被观察者,Single能被各种操作符控制。有些操作符允许保持接口不变的情况下混用,既可以对被观察者使用,也可以对Single使用。
操作符 | 返回值 | 描述 |
---|---|---|
compose | Single | 允许创建自定义操作符 |
concat & concatWith | Observable | 将多个Single产生的事件连接起来,作为某被观察者的事件队列 |
create | Single | 通过明确调用订阅者方法,从头创建一个Single |
delay | Single | 将事件的传递向后延迟一段时间 |
doOnError | Single | 返回Single,当它调用onError() 方法时,也调用指定的一个方法 |
doOnSuccess | Single | 返回Single,当它调用onSuccess() 方法时,也调用指定的一个方法 |
error | Single | 返回Single,它立即给订阅者发送onError() 通知 |
flatMap | Single | 返回Single,它产生的是对原始Single产生的事件使用函数的结果 |
flatMapObservable | Observable | 返回被观察者,它产生的是对原始Single产生的事件使用函数的结果 |
from | Single | 将Future转换成Single |
just | Single | 返回Single,它产生一个特定事件 |
map | Single | 返回Single,它产生的是对原始Single产生的事件使用函数的结果 |
merge | Single | 将第二个Single作为事件产生的Single转换成产生第二个Single的事件的Single |
merge & mergeWith | Observable | 合并多个Single产生的事件作为被观察者的事件 |
observeOn | Single | 通知Single在指定线程上调用订阅者方法 |
onErrorReturn | Single | 将发送onError() 通知的Single转换为产生特定事件的Single |
subscribeOn | Single | 通知Single在特定线程上执行 |
timeout | Single | 返回Single,它发送onError() 通知,当原始Single在特定时间内不产生事件 |
toSingle | Single | 将产生单一事件的被观察者转换成产生那个事件的Single |
toObservable | Observable | 将Single转换成产生原始事件的被观察者,接着发送onCompleted() 通知 |
zip & zipWith | Single | 返回Single,它产生的是对两个以上原始Single产生的事件使用函数的结果 |
下面将通过图例有计划地讲解这些操作符,以及Single如何使用:
3.2.操作符图解
compose
-
concat & concatWith
Concat.png这个操作符还有一个实现版本:
ConcatWith.png -
create
Create.png -
delay
Delay.png这个操作符还有一个实现版本,允许在指定线程上执行延迟:
Delay.png -
doOnError
DoOnError.png -
doOnSuccess
DoOnSuccess.png -
error
Error.png -
flatMap
FlatMap.png -
flatMapObservable
FlatMapObservable.png -
from
From.png还有一个类似的写法,将Scheduler作为参数:
From.png -
just
Just.png -
map
Map.png -
merge & mergeWith
merge()
操作符的一种实现,将第二个Single作为事件产生的Single转换成产生第二个Single的事件的Single:Merge.png另一种实现,合并两个以上Single产生的事件作为被观察者的事件(以任意顺序):
Merge.png -
observeOn
ObserveOn.png -
onErrorReturn
OnErrorReturn.png -
subscribeOn
SubscribeOn.png -
timeout
如果Single在被订阅后的规定时间内不产生一个事件,
timeout()
操作符将通过onError()
通知导致它终止。一种实现允许通过一些指定的时间单位,设置超时时间:Timeout.png也可以指定一个特定的线程给计时器运行:
Timeout.png另一种实现,当超时,允许切换到备份的Single,而不是发送
onError()
通知:Timeout.png这个也有指定Scheduler版本:
Timeout.png -
toObservable
ToObservable.png -
zip & zipWith
Zip.png
4.总结
讲到这里不知道大家发现没有,在订阅之前事件的产生逻辑和处理逻辑已经固定,基本可以预测结果。若是希望在应用运行中,由用户操作控制事件产生的顺序和种类,则需要更灵活的被观察者。下一篇文章将着重讲解,被观察者如何与用户交互。