对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。
回头看一下,翻译的一团糟,英语不好的同学将就的看吧…..
能力有限,欢迎大家提意见。
- 对RxJava Essentials的翻译-Chapter2
- chapter2 Cyclone Architecture的翻译1
- Rxjava教程《RxJava Essentials》中文版
- RxJava-Essentials-CN
- RxJava-Essentials-CN
- RxJava Essentials 中文翻译版
- Papervision3D Essentials 第九章翻译 的下载地址
- RxJava 学习书籍——RxJava Essentials
- 对RxJAVA的理解
- 对RxJava的认识
- 《Papervision3D Essentials》 翻译 chapter 9
- Reactive Programming with RxJava-Chapter2:Reactive Extensions
- 对rxjava的详细解析
- 我对rxjava的理解
- 书写高质量JavaScript代码的要义(The Essentials of Writing High Quality JavaScript)翻译
- 书写高质量JavaScript代码的要义(The Essentials of Writing High Quality JavaScript)翻译
- 书写高质量JavaScript代码的要义(The Essentials of Writing High Quality JavaScript)翻译
- Shared Source CLI Essentials翻译(二):1.2 Rotor:一个CLI的共享源代码实现
- Maven实现直接部署Web项目到Tomcat7
- 两个数的求和差乘积相除。
- java正则表达式验证邮箱、IP地址、手机号码
- 15个顶级Java多线程面试题及回答
- [PHP]GD库生成图像无法在浏览器正常显示的问题(更新:使用GD图像生成类发现错误必须及时清理缓存!)
- 对RxJava Essentials的翻译-Chapter2
- ubuntu下NDK环境搭建
- 遍历Map集合的不同方法
- 蓝桥杯历届试题之回文数字
- android 中 dumpsys 命令使用
- javascript 简介和基础
- CodeForces - 630P Area of a Star (数学几何&正弦定理求面积)
- C#中Abstract和Virtual
- hdu 1158 Employment Planning【dp】