在您获得一个Observable实例之后,了解其strem(即数据流)是热(Hot)的还是冷(Cold)的是很重要的。API和语义保持不变,但是使用Observable的方式取决于类型。cold的的Observable是完全惰性的,从不开始发出事件,直到有人对其真正感兴趣为止(即通过subscribe方法订阅)。如果没有观察者,Observable只是一个静态的数据结构。这也意味着每个订阅者都将收到自己的流副本,不仅因为事件是惰性生成的,而且也不可能以任何方式缓存(译者注:需要慢慢消化)。Cold类型的Observable通常来自于Observable.create(),这种类型的Observable惯于不是积极的启动任何逻辑,而是直到有观察者对其感兴趣为止。因此,Cold类型的Observable在某种程度上取决于用户。除了create()之外,Cold类型的Observable还包括Observable. just()、from()和range()。订阅一个Cold类型的Observable通常会伴随着有发生在create()方法中的副作用。例如,查询数据库或打开连接。
hot类型的Observable是不同的。当你得到这样一个Observable后,它可能早已经在发射事件了,不管他们有多少订阅者。Observable 将事件推送到下游,即使没有人听,事件也可能丢失。然而,一般来说,你完全可以控制cold类型的Observable,然而hot类型的Observable是独立于消费者的。当一个订阅者者出现时,一个hot 类型的Observable表现的就像一个电报机,通过它透明的发布事件流。订阅者的存在与否,不会改变Observable的行为;它是完全解耦和独立的。
令人惊讶的是,Observable.interval()不是hot类型的。您可能认为它只是产生了一些时间间隔的计时器,而不考虑环境,但实际上,计时器事件只有在用户订阅的情况下才产生,并且每个订阅者接收独立流。这是一个cold类型的Observable定义。
当我们完全无法控制事件的来源时,通常会产生Hot 类型的Observable 。这种Observable 的例子包括鼠标移动、键盘输入或按钮点击。到目前为止,我们还没有提到用户界面,但事实证明,在实现用户界面时,RxJava非常适合。这个库在Android社区中特别受欢迎,它有助于从嵌套的回调转换成流的平面组合。我们将在第277页“与RxJava的Android开发”中探讨如何使用RxJava在Android的移动设备上运行。
当我们依赖于事件的传递时,hot与cold类型区分的重要性变得至关重要。无论你什么时候订阅一个Cold类型的Observable——无论是立即还是连续的——你总会收到一套完整的、一致的事件。另一方面,如果Observable是Hot类型的,你就不能确定从一开始就接收到所有的事件。在本章后面,我们将学习如何确保每个订阅方接收所有事件的技巧。其中一种技术已经潜入了这一章:cache()操作符(参见第37页的“管理多个订阅者”)。从技术上讲,它可以从一个Hot类型的Observable中缓存所有事件,并允许后续订阅者接收相同的事件序列。但是,因为它在理论上消耗了无限的内存,所以缓存Hot类型的Observable时候要注意小心。
在Cold和Hot类型的数据源之间的另一个有趣的区别是时间依赖性。一个Cold类型的Observable 会根据需求产生值,并且可能会产生多次,一个条目创建的那个瞬间是无足轻重的。相反,Hot类型的Observable 表示事件的发生,通常来自外部数据源。这意味着,一个给定值生成的瞬间是非常重要的,因为它将事件放置在时间尺度上。