在内部,每个Rx operator都做3件事:
- 它订阅源并观察值。
- 它根据操作员的目的转换观察到的序列。
- 它通过调用onNext,onError和onCompleted将修改后的序列推送到自己的订阅者。
compose运算符使用一种方法,使一个可观察的方法脱离另一个方法。这样做可以省去手动执行上述3个步骤的麻烦:中间订阅和推送隐含在Rx链中。这假设您可以使用现有运算符进行转换。如果运算符尚不存在,则需要以传统的Java OOP方式进行处理。这意味着从管道中提取值并在处理时重新推送。执行此操作的Observable.Transformer将包括对源Observable的显式订阅和/或显式创建要返回的新Observable。
你会发现这通常只是样板,并且你可以通过降低级别来避免一些问题。lift operator与compose的不同之处在于转换Subscriber而不是Observable。
public final <R> Observable<R> lift(Observable.Operator<? extends R,? super T> lift)
并且Observable.Operator <R,T>是Func1<Subscriber<? super R>的别名,Subscriber<? super T>>:将Subscriber <R>转换为Subscriber <T>的函数。通过直接与订阅者交易,我们避免涉及Observable。订阅和创建Observable类型的样板将由lift处理。
在下一个示例中,我们将重新实现map,而不使用现有实现或任何其他现有运算符。
Map运算符需要一个将项从T转换为R的函数。在我们的实现中,这是变换器字段。关键部分是call方法。我们收到一个想要接收R类型项的订阅者<R>。对于该订阅者,我们创建一个新Subscriber<T>,它接收类型为T的项目,将它们转换为R类型并将它们推送到Subscriber<R>。lift处理接收Subscriber <R>的样板,以及使用创建的Subscriber <T>订阅源observable。
使用Observable.Operator就像使用Observable.Transformer一样简单:
日志输出:
Java中的类构造函数不能使用其类型参数。合乎逻辑的最后一步是创建一个可以为我们推断类型的方法
并使用这样的
当手动推送给订阅者时,就像我们在实现Observable.Operator时所做的那样,有几件事需要考虑:
- 订阅者可以自由取消订阅。不先检查就不要推送:!subscriber.isUnsubscribed()。
- 您有责任遵守Rx协议:任意数量的onNext通知,可选地后跟单个onCompleted或onError。
- 如果需要执行异步操作和调度,请使用Rx的调度程序。这将使您的operator变得可测试。
下节再续!