理解RxJava:(二)Operator,Operator

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

让咱们经过一个例子来向大家介绍更多的operators。git

初始

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

//返回一个基于文本查询网站连接的列表
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循环。哎哟。ide

一线但愿

有一个方法,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()url

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翻译。转载请注明出处,并保留此段声明。

相关文章
相关标签/搜索