第一部分,我讲解了RxJava的基本结构,也介绍了map()操作。然而,我能理解你仍旧不会选择使用Rxjava——你仍然还有很多东西没有学到。但是这个情况将很快得到改变。Rxjava一大部分的能力是因为其中的operators。

让我们通过一个例子来向你们介绍更多的operators。

初始

假设我有一个这样的方法:

//返回一个基于文本查询网站链接的列表
Observable<List<String>> query(String text);

我想要构建一个搜索文本和显示结果的强健系统。基于上篇文章我们学到的,以下是我们马上想到的:

query("Hello, world!")
.subscribe(urls -> {
for (String url : urls) {
System.out.println(url);
}
});

这个答案让人非常不满意,因为失去了转换数据流的能力。如果我想要修改每个URL,只能在每个Subscriber里面修改。这就违背了使用map()操作的初衷。

我可以为ulrs->urls创建一个map(),但是每个map()的内部都有一个for-each循环。哎哟。

一线希望

有一个方法,Observable.from(),输入一些items,然后每次发出一个:

Observable.from("url1", "url2", "url3")
.subscribe(url -> System.out.println(url));

看起来有些帮助,让我们看看:

query("Hello, world!")
.subscribe(urls -> {
Observable.from(urls)
.subscribe(url -> System.out.println(url));
});

没有了for-each循环,但是代码显得很混乱。现在变成了多个嵌套的subscriptions了。除了代码丑陋以及难以修改外,也违背了RxJava的一些原则。

更好的方法

屏住你的呼吸,因为你见到了你的救世主:flatMap()

Observable.flatMap()获取一个Observable的返回值,将值发给另一个取代它的Observable。如下:

query("Hello, world!")
.flatMap(new Func1<List<String>, Observable<String>>() {
@Override
public Observable<String> call(List<String> urls) {
return Observable.from(urls);
}
})
.subscribe(url -> System.out.println(url));

我写成完整的方法是为了你能看到发生了什么,但是用 lambda表达式简写看起来很棒:

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.subscribe(url -> System.out.println(url));

flatMap()(看起来)很怪,对吗?为什么返回另一个Observable?核心概念是新的Observable返回的正是Subscriber所观察的。它不接收List<String>——它接收Observable.from()返回的一系列的单独的Strings

此外

我强调这个观点几遍都不足够:flatMap()能返回任意想要的Observable

假设我又有一个这样的方法:

// 返回网站的标题,若是404则返回null
Observable<String> getTitle(String URL);

原本是打印URL,现在我想要打印接收的每个网站的标题。但是有些问题:我的方法只对每次一个URL有效,而且它返回的不是String,它返回的是发出String的Observable

有了flatMap(),解决这个问题很简单。在把一系列的URL分开为单独的items后,我可以在flatMap()方法中对于每个URL使用getTitle(),在它到达Subscriber前。

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.flatMap(new Func1<String, Observable<String>>() {
@Override
public Observable<String> call(String url) {
return getTitle(url);
}
})
.subscribe(title -> System.out.println(title));

同样,使用lambda简写:

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.subscribe(title -> System.out.println(title));

很酷,对吧?我把几个返回Observable方法组合在一起。

不仅仅于此,我还将两个API调用组合在一条方法链上了。你们知道维持所有的API调用同步,必须在数据展示前将它们的回调写在一起,是有多痛苦?我们不用再忍受嵌套回调了。所有的逻辑都包在简短的响应式调用中了。

大量的Operators

到目前为止,我们仅仅学习了两种operators。有很多还没有学到。其他的operators能怎样改善我们的代码呢?

getTitle()在URL404的时候返回null。我们不想要输出"null"。以下代码显示我们可以过滤掉null:

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.filter(title -> title != null)
.subscribe(title -> System.out.println(title));

filter()方法发出和它们接收到的同样的item,只在通过了boolean检查的情况下。

现在我们只想要最多显示5个结果:

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.filter(title -> title != null)
.take(5)
.subscribe(title -> System.out.println(title));

take()最多发出指定数量的item(如果少于5个标题,它会提前停止)。

现在我们想要存储每个标题到磁盘上:

query("Hello, world!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.filter(title -> title != null)
.take(5)
.doOnNext(title -> saveTitle(title))
.subscribe(title -> System.out.println(title));

doOnNext()让我们可以在每次一个item被发出之前,添加额外的行为。

看操作数据流多么简单。你可以继续对数据添加操作而不会弄糟任何事情。

RxJava有非常多的Operators。这么多operators让我们被吓到,但是值得查阅一遍以知道哪个对我们有用。消化这些操作会花费点时间,但是我们能信手拈来的时候就能感受到Rxjava真正的强大。

以上都是官方提供的,我们甚至可以自定义operators!这超出了本文的讨论范围。但是只要你想你就能做到。

So What?

如果你是个怀疑论者。你会问为什么要关注这些operators?

关键点3 Operators让你能对数据流做任何事

唯一的限制就是你自己。

你可以处理复杂的逻辑,从使用简单的operators链开始。它将你的代码打破为可重组的零碎东西。这就是函数响应式编程。你用的越多,就越能改变你编程的思维。

另外,想想我们的代码一转换消费起来变得多容易。最后的例子,我们调用了两次API,操作数据,然后存储。但是Subscriber并不知道这些。它想的仅仅是消费Observable<String>。封装让编程更简单。

在第三部分,我们将继续了解RxJava的特性。比如错误处理和并发,和操作数据没有直接联系。

本文翻译自Grokking RxJava, Part 2: Operator Operator,著作权归原作者danlew所有。译文由JohnTsai翻译。转载请注明出处,并保留此段声明。

理解RxJava:(二)Operator,Operator的更多相关文章

  1. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  2. 理解RxJava:(三)RxJava的优点

    理解RxJava:(三)RxJava的优点 在第一部分,讲解了RxJava的基本结构.在第二部分,展示了operators的强大之处.但是你们可能仍然没有被说服,也没有足够的理由信服.下面是一些能让你 ...

  3. 理解RxJava:(一)基础知识

    理解RxJava:(一)基础知识 本文翻译自Grokking RxJava, Part 1: The Basics,著作权归原作者danlew所有.译文由JohnTsai翻译.转载请注明出处,并保留此 ...

  4. C++ 中类的构造函数理解(二)

    C++ 中类的构造函数理解(二) 写在前面 上次的笔记中简要的探索了一下C++中类的构造函数的一些特性,这篇笔记将做进一步的探索.主要是复制构造函数的使用. 复制构造函数 复制构造函数也称拷贝构造函数 ...

  5. ppp 完全理解(二)【转】

    转自:https://blog.csdn.net/tianruxishui/article/details/44057717 ppp 完全理解(二) pppd 协议及代码分析 作者:李圳均 日期:20 ...

  6. Java 反射理解(二)-- 动态加载类

    Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编 ...

  7. (二) operator、explicit与implicit 操作符重载

      有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成把两个整 ...

  8. Flink笔记(二) DataStream Operator(数据流操作)

    DataStream Source 基于文件 readTextFile(path) 读取 text 文件的数据 readFile(fileInputFormat, path) 通过自定义的读取方式, ...

  9. 理解RxJava线程模型

    RxJava作为目前一款超火的框架,它便捷的线程切换一直被人们津津乐道,本文从源码的角度,来对RxJava的线程模型做一次深入理解.(注:本文的多处代码都并非原本的RxJava的源码,而是用来说明逻辑 ...

随机推荐

  1. 只有好的棋手才会走运-《打造Facebook》读后感

    王淮的<打造Facebook>一书不厚,花半天时间轻松读完.书中没有大段的说教,只有近乎流水的陈述.正如作者所说,打造Facebook这本书由巴克伯格来写再合适不过.可惜他至少在近几年内没 ...

  2. 理解Javascript的异步等待

    目前async / await特性并没有被添加到ES2016标准中,但不代表这些特性将来不会被加入到Javascript中.在我写这篇文章时,它已经到达第三版草案,并且正迅速的发展中.这些特性已经被I ...

  3. 深入理解javascript事件流

    摘要:事件流这个东西是比较重要的,为了让自己更加理解js中的事件流,必须整理整理,梳理一下事件流的各种东西啊.本文大部分内容参考<javascript高级程序设计第三版> 先来一段书里的原 ...

  4. 25款顶级的jQuery表格插件

    jQuery 表格插件可以让你创建各种各样的表格布局,表格布局是报纸和杂志中最常见的布局,现在的网站中也很常见,在这篇文章中,我向大家推荐25个jQuery 的表格插件,你可以任意控制表格的行和列,用 ...

  5. paip.关于动画特效原理 html js 框架总结

    paip.关于动画特效原理 html js 框架总结 1. 动画框架的来源:flex,jqueryui 3 2. 特效的分类 3 2.1. Property effects 动态改变一个或多个目标对象 ...

  6. Extjs4中RadioGroup的赋值与取值

    1.定义rg var rg = new Ext.form.RadioGroup({ fieldLabel : "test", items : [{ boxLabel : '每天', ...

  7. PHP实现微信公众账号开发

    1.首先需要一个可以外网访问的接口url. 我这里是申请的新浪免费云服务器,http://xxxxx.applinzi.com/wx.php,具体自己可以去新浪云中心申请地址为:http://www. ...

  8. Android版-支付宝APP支付

    此项目已开源 赶快来围观 Start支持下吧 [客户端开源地址-JPay][服务端端开源地址-在com.javen.alipay 包名下] 上一篇详细介绍了微信APP支付 点击这里 此篇文章来详细介绍 ...

  9. Passwordless SSH Login

    原文地址:http://manjeetdahiya.com/2011/03/03/passwordless-ssh-login/ Consider two machines A and B. We w ...

  10. Lotus开发性能优化

    之前也总结过一篇关于性能的文章,地址在http://www.cnblogs.com/carysun/archive/2008/08/09/BasicPerformance.html,今天又看到DW上又 ...