对RxJava Essentials的翻译-Chapter2

来源:互联网 发布:马桶品牌知乎 编辑:程序博客网 时间:2024/05/29 17:55

https://github.com/yuxingxin/RxJava-Essentials-CN写完才发现这里有完整的翻译……

最近看了RxJava Essentials,主要是对RxJava操作符的一些介绍,本人准备翻译一遍,内容有点多,希望能够全部翻译完。有缺点和不足的地方,欢迎大家补充。从chapter2开始

chapter2 为什么是Observablers?

在面向对象结构中,开发者努力地创造解耦的实体类。这样,就可以在不妨碍整个系统的情况下对实体类进行测试、重用和维护。设计这样的系统带来了一个麻烦的副作用:维护相关联类之间的一致性。

第一个用来解决这个问题的模式是SmallTalk中的Model-View-Controll结构。用户交互层提供方法使得UI元素和持有数据的类分离,同时,它提供了一个方便的方法方式使得一切都保持同步。

观察者模式是一个在由Gang of Four写的《Design Patterns: Elements of Reusable Object-Oriented
Software》中最著名的模式之一。这是一种能够在一对多依赖中绑定数据的行为模式:当一个类有变化时,所有依赖它的类都能够通知,并且自动更新状态。

在这一章,我们会对观察者模式有个大致的概念,它是如何被RxJava实现扩展的,什么是观察者,观察者是如何与可迭代对象关联的。

观察者模式

如今,观察者模式是在开发中应用最普遍的设计模式之一。它是基于subject(这个不造该怎么翻译…)概念的。subject是一个特殊的类,它持有一系列的类,这些类希望在subject变化时会被通知到。这些类就被称为观察者,它们会暴露一个通知方法,当subject类状态改变时会调用这个方法。

在前面的章节中,我们看了表格的例子。现在我们可以扩展这个例子,展示一个更复杂的场景。我们假设一个包含账户和数据的表格。我可以以表格、3D柱状图或者饼状图展示这些数据。每一种展示的方式都是基于相同的一组数据。每一种展示方式都是一个观察者,他们基于同一组数据,持有所有的信息。

3D柱状图类、饼状图类、表格类和其他持有数据的类都完美的解耦了:他们可以独立的被使用和复用,但是他们也能同时工作。展示类之间互相不知道,但是他们表现得好像他们之间相互知道:他们知道去哪找要展示的数据、他们知道当数据变化时要更新展示的数据。
下图描述了Subject/Observer 的关系是一对多的关系:
这里写图片描述

上图展示了一个单独的subject可以为多个观察者服务。显然,没有理由限制观察者的数量:如果有需要,subject可以有无数多个观察者,并且当subject状态变化时,每个观察者都能收到通知。

我们什么时候使用观察者模式?

观察者模式完美地适合用于一下场景:

  • 当你的结构有两个实体类,一个依赖另一个,并且你想能够单独的改变或者重用他们。
  • 当一个变化的object需要通知数量未知的相关object自己的状态变化的时候
  • 当一个变化的object需要通知未知的其他的object的时候

RxJava 观察者模式

在RxJava的中,有四个主要的成员:
- Observable
- Observer
- Subscriber
- Subjects

Observables和Subjects是两个“生产”类。Observers和Subscribrs是两个“消费”类。

Observable

当我们要异步执行一些轻量级的任务时,Java提供了一些经典的类用了解决这个问题,例如:Thread、Future、FutureTask和CompletableFuture。当任务的复杂性升高时,这些解决方案就变得凌乱并且难以维护。更重要的是,他们不能链式调用。

RxJava Observables就是设计用了解决这些问题的。它更灵活并且易于使用,可以链式调用,甚至可以工作在同一个序列中。当你想要发送一个单独的数值或者一组数值,甚至一个无限的数据流时,你可以使用Observable。
Observable 的生命周期包含三个事件,我们可以和Iterable的生命周期对比一下,下面的表格展示了Obserable的 async/push方法和Iterable的sync/pull的对比:
这里写图片描述
在Iterable中,消费者从生产者同步拉取数据,在数据到达前,线程是阻塞的。相比之下,在Observable中,生产者在有可用数据时把数据异步的推送给Observer。这种方式更为灵活,因为不管数据同步还是异步到达,消费者都能够根据预期做出反应。
为了更好的复制Iterable的接口,RxJava Observable类强化了观察者模式的基本语义,并且引入了两个新的方法:

  • onComplete(),通知Observer不会从Observable收到数据了。
  • onError(),通知Observer发生了错误。
    记住这两个方法和之前的表格,我们知道Observables有堪比Iterables的方法,但是有不同的数据流向:push和pull。

冷启动、热启动Observables

从发送数据的角度讲,有两种不同类型的Observable:热启动和冷启动Observable。热启动Observable一创建就会开始发送数据,因此任何订阅了这类Observable的Observer可能会在数据流的中间开始接收数据。冷启动Observable会等待,直到Observer订阅了它才会开始发送数据,因此Observer可以保证接收到完整的数据流。

创建一个Observable

Observable类提供了以下方法来创建Observable

Observable.create()

开发者可以使用create()方法创建一个Observeble。当Observable订阅Observer时,它接收一个OnSubscribe类型的参数,并且执行call()方法。

Observable.create(new Observable.OnSubscribe<Object>() {@Overridepublic void call(Subscriber<? super Object> subscriber) {}});

Observable通过subscriber 变量调用它的方法和Observer通信。让我们看一个真实的例子:

Observable<Integer> observableString =            Observable.create(new Observable.OnSubscribe<Integer>() {                @Override                public void call(Subscriber<? super Integer> observer) {                    for (int i = 0; i < 5; i++) {                        observer.onNext(i);                    }                    observer.onCompleted();                }            });    Subscription subscriptionPrint =            observableString.subscribe(new Observer<Integer>() {                @Override                public void onCompleted() {                    System.out.println("Observable completed");                }                @Override                public void onError(Throwable e) {                    System.out.println("Oh no! Something wrong happened!");                }                @Override                43                public void onNext(Integer item) {                    System.out.println("Item is " + item);                }            });

这个例子故意写得很简单,因为即使是第一次接触RxJava,我也想让你弄明白到底发生了什么。
我们创建了一个新的Observable 对五个元素执行for循环,依次发送五个元素,然后结束。
另一方面,我们订阅了Observable,获得一个Subscription对象。当我订阅时,就开始接受整形数值并依次打印。我们不知道会接收多少个数值。事实上,我们不需要知道,因为我们为每一个可能的场景都提供了不同的行为:

  • 如果接收一个整型数值,打印出来
  • 如果序列结束,打印一个结束序列的信息
  • 如果发生错误,打印错误信息

Observable.from()
在前面的例子中,我们创建了一个整型序列,并且依次发送出去。如果我们已经有一个列表呢?我们能够在保留for循环的情况下仍然依次发送元素吗?
在下面的代码中,我们从已有的列表创建一个Observable序列:

List<Integer> items = new ArrayList<Integer>();    items.add(1);    items.add(10);    items.add(100);    items.add(200);    Observable<Integer> observableString = Observable.from(items);    Subscription subscriptionPrint =            observableString.subscribe(new Observer<Integer>() {                @Override                public void onCompleted() {                    System.out.println("Observable completed");                }                @Override                public void onError(Throwable e) {                    System.out.println("Oh no! Something wrong happened !");                }                @Override                public void onNext(Integer item) {                    System.out.println("Item is " + item);                }            });

输出和前面的例子完全一致。
from()方法可以从列表/数组创建Observable,依次发送其中的元素,或者从Java中的Future类的get()方法发送结果。传入Future作为参数,我们甚至可以指定超时时间。Observable会等待来自Future的结果,如果在超时前没有结果到达,Observable会触发onError() 方法,并且通知Observer出错了。

Observable.just()

如果我们已经有一个Java方法,并且想要把他传给Observable呢?我们已经知道可以使用create()方法,或者我们使用一下代码避免很多引用代码:

 Observable<String> observableString =            Observable.just(helloWorld());    Subscription subscriptionPrint =            observableString.subscribe(new Observer<String>() {                @Override                public void onCompleted() {                    System.out.println("Observable completed");                }                @Override                public void onError(Throwable e) {                    45                    System.out.println("Oh no! Something wrong happened!");                }                @Override                public void onNext(String message) {                    System.out.println(message);                }            });

helloworld() 方法十分简单:

private String helloWorld() {    return "Hello World";}

当然,这里可以是我们想要的其他函数。在前面的例子中,一旦我们创建了Observable,just() 执行函数,同时,当我们订阅Observable时,它开始发送返回的数值。
just() 方法可以接收一到九个参数。它会按照接收的参数的顺序依次发送这些参数,just() 方法同时也接收列表或者数组参数,类似from() ,但是它不会遍历列表发送每个元素,而是直接发送整个列表。一般情况下,当我们想发送定义好的一组数据时,我们可以用这个方法,但是如果我们的函数不是时变的(注:这里原文是but if our function is not time-variant,不知道翻译过来是什么意思),我们可以用just() 方法来生成更有有序、可测试的代码。
关于just()最后需要注意的一点,当发送完数据后,Observable就正常结束了。对于前面的例子,我们会在控制台看到两条数据:“hello world”和“Observable completed”。

Observable.empty(), Observable.never(), and Observable.throw()
如果在某些原因下,我们需要Observable什么都不发送但是正常终止,我们可以使用empty() 。我们可以用never() 创建一个什么都不发送,也不会终止的Observable。throw() 可以用来创建不发送数据并且以错误终止的Observable。

Subject=Observable+Observer

subject 是一个神奇的类,它可以既可以是Observable,也可以是Observer:它就像连接两个世界的桥梁。subject可以作为Observer订阅一个Observable,也可以发送作为Observable发送数据,甚至发送它接收到的数据。显然,作为Observable,Observer或者其他subject可以订阅它。

subject订阅Observable的时候,它会触发Observable发送数据。如果这个Observable是“冷”Observable,这会使得之前“冷启动”Observable转变成“热启动”Observable(*注:原文,this can have
the effect of making the resulting subject a hot Observable variant of the
original cold Observable*)。
RxJava提供了四种不同类型的subject:

  • PublishSubject
  • BehaviorSubject
  • ReplaySubject
  • AsyncSubject

下面的内容就不翻译了…….好多,并且好像在android中没看见有用到这几个类的…有兴趣的同学自己看吧…..
这里写图片描述

总结
这一章,我们学习了什么是观察者模式,为什么观察者模式这么重要,以及我们如何创建Observables和Subjects。
下一章,我们会基于RxJava创建第一个android app,学习如何如何获取数据填充ListVIew,并且探索如何基于RxJava创建响应式的UI。

回头看一下,翻译的一团糟,英语不好的同学将就的看吧…..
能力有限,欢迎大家提意见。

0 0
原创粉丝点击