理解RxJava:(一)基础知识

理解RxJava:(一)基础知识

本文翻译自Grokking RxJava, Part 1: The Basics,著做权归原做者danlew全部。译文由JohnTsai翻译。转载请注明出处,并保留此段声明。java

RxJava这些天成为了Android开发者关注的新热点。惟一的问题是它在你刚接触时难以理解。当你习惯了命令式编程,函数响应式编程就变得难以理解。可是一旦你理解了它,它就变得很棒了。react

我在这试着给大家带来不同的RxJava。这一系列四篇文章的目标是带大家入门。我不会也不能讲解全部的东西。我只是想让大家对RxJava以及它的工做原理感兴趣。git

基础知识

响应式代码的基本构成部分是ObservablesSubscribers(译者注:技术名词很难找到合适的中文翻译,因此维持原文不被翻译)。Observable发出items,Subscriber消费这些items。github

items如何被消费有一套规则。Observable发出任意数量的items(包括0个items),要么以成功完成终止,要么以发生错误终止。对于Observable的每一个Subscriber,Observable调用Subscriber.onNext()方法任意次,而后调用Subscriber.onComplete()方法或Subscriber.onError()方法。数据库

这看起来和咱们用的观察者模式相似,但在一个关键地方不一样——Observables在有人明确地订阅它以后才会开始发出items。换句话说,没有人去订阅,就不会发出订阅事件(译者注:引伸自If a tree falls in a forest)。编程

Hello World

让咱们经过一个具体例子来看RxJava是如何运做的。首先,先建立一个基本的Observable:网络

Observable<String> myObservable = Observable.create(
    new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> sub) {
            sub.onNext("Hello, world!");
            sub.onCompleted();
        }
    }
);

Observable发出Hello World而后完成。如今建立一个Subscriber来消费掉数据。框架

Subscriber<String> mySubscriber = new Subscriber<String>() {
    @Override
    public void onNext(String s) { System.out.println(s); }

    @Override
    public void onCompleted() { }

    @Override
    public void onError(Throwable e) { }
};

全部这些所作的是将Observable发出的每一个String打印出来。ide

如今有了myObservablemySubscriber,咱们能够用subscribe()方法将它们链接起来。函数

myObservable.subscribe(mySubscriber);
// 输出 "Hello, world!"

当订阅发生时,myobservable调用subsriberonNext()onComplete()方法。做为结果,mySubscriber输出"Hello,World"而后结束。

更简洁的代码

为了输出"Hello,World!",上面写了许多样板代码。这是由于我为了让大家可以明确发生了什么,选择了一种啰嗦的方式。RxJava提供了许多快捷写法让咱们能写出更简洁的代码。

首先,简化Observable。RxJava有针对通用任务的多种内置Observable构建方法。在这种状况下,Observable.just()发出一个item而后完成结束,就像咱们上面的代码:

Observable<String> myObservable =
    Observable.just("Hello, world!");

而后,对于啰嗦的Subscriber。咱们不关心onCompleted()onError()方法,取而代之,咱们能够用一个更简洁的类来定义在onNext()中作什么:

Action1<String> onNextAction = new Action1<String>() {
    @Override
    public void call(String s) {
        System.out.println(s);
    }
};

Subscriber每部分的Action都能自定义。Observable.subscribe()能处理一个,两个以及三个Action参数,以取代onNext(),onError()onComplete()方法。复用咱们以前的Subscriber,以下:

myObservable.subscribe(onNextAction, onErrorAction, onCompleteAction);

然而,咱们仅仅须要第一个参数,由于咱们能够省略onError()onComplete()方法:

myObservable.subscribe(onNextAction);
// 输出 "Hello, world!"

如今,让咱们经过方法的链式调用来取代这些变量:

Observable.just("Hello, world!")
    .subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
              System.out.println(s);
        }
    });

最后,用Java 8的lambdas表达式来去掉丑陋的Action1代码。

Observable.just("Hello, world!")
    .subscribe(s -> System.out.println(s));

若是你在Android中使用(迄今为止不能使用Java8)(译者注:原文做者写这篇文章的时候(2014年)Java8在Android中开发不能使用,在译者翻译这篇文章的时候(2016年),已经能使用部分特性了),我推荐使用retrolambda,它将大幅下降代码的啰嗦程度。

变换

让咱们把事情变得更有趣。

假设我想要在输出的"Hello,world!"语句中加上个人签名。一种可能(的实现方式)是改变Observable:

Observable.just("Hello, world! -Dan")
    .subscribe(s -> System.out.println(s));

若是你可以控制你的Observable,这有效。可是不能保证之后都是这种状况。若是你使用的是别人的库呢?
另外一种可能的问题是:若是我在多个地方使用个人Observable,但仅仅是某些状况下想要加上签名呢?

那修改咱们的Subscriber怎样:

Observable.just("Hello, world!")
    .subscribe(s -> System.out.println(s + " -Dan"));

这个回答一样不能让人满意,有不一样的缘由:我想要个人Subscriber尽量轻量,由于我可能会在主线程上运行它们。在更概念的层次上理解,Subscribers被认定是作出反应(reacts)的事物,而不是作出转变(mutates)的事物。

若是我可以经过一些中间步骤将"Hello,world!"转换,是否是很酷?

Operators介绍

接下来是如何解决item转换问题:使用operators。Operators被用于在源Observable和最终的Subscriber之间操做被发出的items。RxJava推出了很是多的operators,可是刚开始咱们仅仅须要关注少数几个。

对于这种状况,map()操做能被用于将一个被发出的item转化为另外一个:

Observable.just("Hello, world!")
    .map(new Func1<String, String>() {
        @Override
        public String call(String s) {
            return s + " -Dan";
        }
    })
    .subscribe(s -> System.out.println(s));

一样的,咱们能使用lambda来简化这个:

Observable.just("Hello, world!")
    .map(s -> s + " -Dan")
    .subscribe(s -> System.out.println(s));

很是酷,咱们的map()操做是一个转换一个item的Observable。咱们能够链式调用任意个map()
,将数据改进,成为最终的Subscriber可消费的形式。

深刻map()

map()有一个有趣的方面:它不须要发出和源Observable相同类型的items!

假设个人Subscriber对输出原文本不感兴趣,想要输出原文本的hash码:

Observable.just("Hello, world!")
    .map(new Func1<String, Integer>() {
        @Override
        public Integer call(String s) {
            return s.hashCode();
        }
    })
    .subscribe(i -> System.out.println(Integer.toString(i)));

很是有趣——咱们以String开始可是咱们的Subscriber接收的是一个Integer。

一样地,咱们能使用lambda来简化代码:

Observable.just("Hello, world!")
    .map(s -> s.hashCode())
    .subscribe(i -> System.out.println(Integer.toString(i)));

就像我以前说的,咱们想要Subscriber尽量少作事。经过另外一个map()来将hash码转化为String:

Observable.just("Hello, world!")
    .map(s -> s.hashCode())
    .map(i -> Integer.toString(i))
    .subscribe(s -> System.out.println(s));

你有没有发现——ObservableSubscriber回到了它们以前的样子了!咱们仅仅在它们之间增长了一些转换步骤。甚至可以添加个人签名:

Observable.just("Hello, world!")
   .map(s -> s + " -Dan")
   .map(s -> s.hashCode())
   .map(i -> Integer.toString(i))
   .subscribe(s -> System.out.println(s));

So What?

此刻你可能会想"对于一些简单的代码,用了不少花式步伐同样技巧"。对,那是简单的例子。可是有两点你须要掌握:

关键点1:ObservableSubscriber能作任何事情

Observale能够是数据库查询,Subscriber获得结果并将它们显示在屏幕上。Observable能够是屏幕上的点击,Subscriber对它作出反应。Observable能够是从网络读取的字节流,Subscriber把它写入磁盘。

RxJava是个可以处理任何问题的通用框架。

关键点2:ObservableSubscriber独立于在它们之间的转换步骤

我能够调用任意次的map操做,在最初的源Observable和它最终的Subscriber之间。RxJava高度组件化:易于操做数据。只要操做于正确的输入输出数据,我能够制造一条无止尽的方法链。

综合以上两点,咱们能够看到RxJava的巨大潜力。虽然此时咱们仅仅有一个map()操做,这严重地限制了咱们的能力。在第二部分,咱们将深刻研究更多RxJava的操做。

相关文章
相关标签/搜索