RxJava 学习笔记 <四> Sequence 基础

 Sequence basics

既然你已经知道了什么是 Rx,现在是开始创建和操作 sequences 的时候了。操作 sequences 的最初实现是基于c#linq,而后者则是从函数式编程中得到启发的。对于这些知识并不是必要的,但是它会使读者更容易学习。根据原始的www.introtorx.com,我们也将操作划分为通常从简单到更高级的主题。大多数 Rx 运算符操作现有序列。但是首先,我们将看到如何创建一个 Observable 开始。

Creating a sequence

在前面的示例中,我们使用了 Subject 并手动将值推入其中以创建序列。我们使用该序列演示了一些关键概念和第一个也是最重要的 Rx 方法--Subject。在大多数情况下,Subject 并不是创造一个新的 Observable 最佳方式。我们现在将看到更整洁的方法来创造可观察的序列。

Simple factory methods

Observable.just

Just方法创建一个 Observable,它将发出预先定义的值序列,在创建时提供,然后终止。

输出:

Observable.empty

observable 会调用单一的 onCompleted 方法,没有其他的。

输出:

Observable.never

这个 observable 不会输出任何值

输出:

Observable.error

该 observable 会发出 error 事件和终止

输出:

Observable.defer

defer 并不定义一种新的 observable ,而是允许您在每次 subscriber 到达时都声明如何创建 observable。考虑如何创建一个 observable ,返回当前时间并终止。您正在发出一个值,因此它听起来就像一个 just。

输出:

注意 subscribers 分开1秒执行,但是看看同一时间。这是因为时间的值只请求了一次:当执行到达 just时。您想要的是当订阅者通过 subscribing 请求时要重新定义的时间。延迟将执行一个函数来创建和返回 Observable 。函数返回 Observable 延迟的,这里最重要的一点是,这个函数将再次执行每一个新 subscription 。

Observable.create

creat 是一个非常强大的功能来创建 observables,让我们看看签名。

static <T> Observable<T> create(Observable.OnSubscribe<T> f)

O使用nSubscribe<T>比它看起来简单。它基本上是一个函数,对于T类型,它接接受 Subscriber<T> ,我们可以手动确定推送事件到 subscriber 。

输出:

当有人订阅 observable (value)时,相应的 Subscriber 实例传递给您的函数。当代码执行时,值被推送到订 Subscriber。注意,如果您想要 sequence 来指示其完成,您要自己调用 onCompleted。

当现有的快速方法都不符合您的目的时,这个方法应该是您首选的创建自定义的 observable 。代码类似于我们如何创建一个 subject 并将 value 推送给它,但是有几个重要的区别。首先,事件的源被整齐地封装,并与无关的代码分离。第二,subject 所包含的危险并不明显:对于管理状态的 subject ,任何访问实例的人都可以将值推入其中并更改顺序,稍后我们会看到更多关于这个问题的内容。

使用 subject 的另一个关键区别在于代码是惰性地执行的,当 observer 订阅时,代码执行。在上面的示例中,当创建 observable 时,代码并没运行(因为尚未订阅服务器),但是每次调用订阅都是这样。这意味着每个订阅服务器都会再次生成每个值,类似于ReplaySubject。最终结果类似于一个ReplaySubject,但没有发生缓存。但是,如果我们习惯使用使用 ReplaySubject,创建方法比较耗时,那么就会阻塞执行创建的线程。您必须手动创建一个新线程来将值推送到 subject中。我们还没有提出并发性的方法,但是也有一些方便的方法来并行执行中的函数。

您可能已经注意到,您可以使用 Observable.create 来实现以前的任何一个 observables。实际上,我们的创建示例相当于 Observable.just("hello")。

Functional unfolds

在函数式编程中,通常会创建长度不受限制或无限长的序列。RxJava有工厂方法来创建这样的序列。

Observable.range

对程序员来说都是直接的和熟悉的方法,它发出指定的整数范围。

Observable<Integer> values = Observable.range(10, 15);

这个例子的发出值的整数范围 10 到24 之间。

Observable.interval

此函数将创建一个无限的序列,以指定的持续时间分隔。

输出:

直到我们不再 unsubscribe 啦,这个 sequence 才会终止。

我们应该注意为什么在结尾的 read()方法是必要的。没有它,程序就会终止,而不会打印内容。这是因为我们的操作是非阻塞的:我们创建了一个 observable ,随着时间的推移,我们会发出值,然后,如果值到达的话,我们会注册执行这些操作。所有这些都不是阻塞的,主线程终止,计时器在自己的线程上运行,这并不阻止JVM终止。

Observable.timer

对于Observable.timer有两个重载。第一个示例创建一个observable 等待给定时间,然后发出 0L 并终止。

输出:

第二个会等待一定的时间,然后以给定的频率开始像间隔一样发出。

输出:

上面的例子等待两秒后,每秒开始计数。

Observable.from

与我们迄今所看到的大部分功能一样,您可以将任何类型的输入使用 create 转换为Rx observable。

Future 是 java 框架的功能,当你使用并发性的框架的时候可能使用他们。它们是一个和 RX 差不多强大的并发概念,因为它们只返回一个值。自然地,您可能希望将它们变成 observables 。

输出:

observable 在可用时发出futureTask 的结果,然后终止。如果任务被取消,可观察到的将发出一个java.util.concurrent.CancerationException error。

如果您对 Future 的结果返回时间限制感兴趣,您可以提供这样的超时机制。

Observable<Integer> values = Observable.from(f, 1000, TimeUnit.MILLISECONDS);

如果 Future 没有在指定的时间内完成,observable 将忽略它,以 TimeoutException 失败。

您还可以使用 Observable.from 将任何集合转换成 observable,这样每个值都会发出,执行最后的 onCompleted 事件。

输出:

Observable 不是可以用Iterable或stream 替换的。Observables 是基于 push-based, 也就是说,调用onNext 会导致处理程序堆栈全部执行到最终订阅服务器方法(除非另有指定)。其他模型是基于  pull-based,这意味着在返回结果之前,尽可能快地请求值和执行块。

参考:

https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%202%20-%20Sequence%20Basics/1.%20Creating%20a%20sequence.md

猜你喜欢

转载自my.oschina.net/u/2277632/blog/1634844