了解RxJava之基础(一)
2016-03-29 17:06
357 查看
原文链接:Grokking RxJava, Part 1: The Basics
RxJava最近在Android开发者中火了起来。唯一的问题是入门比较困难,尤其是当你来自命令式编程的世界,但是一旦理解它,你就会发现RxJava真是太棒了。
这里仅仅是带你了解RxJava。整个系列共四篇文章,我希望你通过阅读之后对RxJava产生兴趣并了解RxJava的原理。
有对事件发射的模式。一个Observable可以发射任何事件(零个或者多个),直到结束或出错。对于每一个Subscriber,一个Observable调用Subscriber.onNext()任意次数,随后调用Subscriber.onComplete() 或 Subscriber.onError()。
这看起来很像标准的观察者模式,但它在一个关键的方法上有所不同。Observables往往不启动发射事件,直到有人显式的订阅这些事件。
我们的Observable发射字符串”Hello, world!”,然后完成。现在让我们创建一个Subscriber消费这个数据:
这里仅仅是打印Observable发射的每个字符串。
现在我们通过subscribe()使myObservable和mySubscriber建立连接:
当订阅建立之后,myObservable调用mySubscriber的onNext和onComplete方法。mysubscriber输出“Hello, world!”,然后终止。
首先,让我们简化Observable创建,,RxJava对常见任务,有多个内置的操作符。在这种情况下,Observable.just()发射单个事件然后完成,就像上面的代码:
接下来,我们处理Subscriber中不需要的回调,在上面例子中我们只是让Observable发送一个数据,而且我们并没有覆写onComplete()和onError(),所以我们用一个简单的类定义在onNext()中做什么:
Actions可以定义Subscriber的每一个动作,例如onNext(),onError,onComplete():
然而,我们只需要第一个参数,因此先忽略onError()和onComplete():
现在,让我们通过链式调用的方法摆脱那些变量:
最后,让我们使用Java 8 的lambdas表达式避免这么丑陋的Action1代码:
如果你使用Android(因此不能使用Java 8),我强烈推荐你使用retrolambda,它能极大了减少冗长的代码。
假设我想要在”Hello, world!”后追加签名,一种可能就是改变Observable,像这样:
这样只能在你的Observable是在你的控制之下,但不能保证总在这样的情况。假如你使用第三方库,一个潜在的问题:Observable在多处使用,但是只有一次需要附加签名,怎么做呢?
我们尝试修改我们的Subscriber,怎么样?
这个答案也不尽人意,因为我想要Subscribers尽量的简单,Subscribers可能需要在主线程中运行。从概念层面,Subscribers应该是响应事件,而非修改事件。
那岂不是很酷,如果我可以在一些中间步骤改变“Hello, world!”?
下面我要解决数据变换的问题,通过介于Observable与Subscriber之间的操作符。RxJava带有大量的操作符集合,但我们目前最好只关注极少数。
对于这种情况,map()操作符可以用于变换被发射的数据:
我们再次通过lambda表达式简化:
很酷,不是吗?我们的map()操作符变换发射的数据并返回另外的Observable,我们可以链式调用map(),变换数据到Subscriber最终消费形式。
假定我的Subscriber对输出原文本不感兴趣,而是要输出文本的哈希值:
有趣,我们开始用一个字符串,但最终我们的Subscriber收到一个整数,我们再次用lambda表达式简化这段代码:
如我之前所说,我们希望我们的Subscriber尽可能做的更少,我们用另一个map把字符串哈希转会字符串:
请看:我们的Observable和Subscriber都回到了他们原来的代码,我们只是增加了一些转换步骤。我们同样可以添加我的签名然后变换:
1.Observable和Subscriber可以做任何事情
Observable发射的事件可以来自是一个数据库查询,Subscriber用来显示查询结果;也可以来自屏幕上的点击事件,Subscriber用来响应点击事件;Observable可以是一个网络请求返回的数据流,Subscriber用来向硬盘写入结果。
这是一个可以处理任何问题的通用框架。
2.Observable和Subscriber是独立于中间的变换过程的
在Observable和Subscriber中间可以链式调用很多map操作符,该系统具有高度的可组合性:它很容易操纵数据。只要操作符数据输入输出都正确,就可以一直链式调用下去。
结合以上两个主要的想法,你可以看到一个具有很大的潜力的系统,虽然当前我们只知道map操作符,这严重限制了我们的能力。在第2部分,我们将畅游RxJava提供的大量操作符。
RxJava最近在Android开发者中火了起来。唯一的问题是入门比较困难,尤其是当你来自命令式编程的世界,但是一旦理解它,你就会发现RxJava真是太棒了。
这里仅仅是带你了解RxJava。整个系列共四篇文章,我希望你通过阅读之后对RxJava产生兴趣并了解RxJava的原理。
0x00 基础
响应式程序的核心是Observables和Subscribers。Observable发出一系列事件,Subscriber处理这些事件。有对事件发射的模式。一个Observable可以发射任何事件(零个或者多个),直到结束或出错。对于每一个Subscriber,一个Observable调用Subscriber.onNext()任意次数,随后调用Subscriber.onComplete() 或 Subscriber.onError()。
这看起来很像标准的观察者模式,但它在一个关键的方法上有所不同。Observables往往不启动发射事件,直到有人显式的订阅这些事件。
0x01 Hello, World!
让我们以一个具体的例子来看看这个框架。首先,让我们创造一个基本的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发射的每个字符串。
现在我们通过subscribe()使myObservable和mySubscriber建立连接:
myObservable.subscribe(mySubscriber); // Outputs "Hello, world!"
当订阅建立之后,myObservable调用mySubscriber的onNext和onComplete方法。mysubscriber输出“Hello, world!”,然后终止。
0x02 简化代码
这里有很多样板代码仅是要打印“Hello, world!”,这么啰嗦就是想让你了解发生了什么。RxJava提供了许多便捷方式以简化编程。首先,让我们简化Observable创建,,RxJava对常见任务,有多个内置的操作符。在这种情况下,Observable.just()发射单个事件然后完成,就像上面的代码:
Observable<String> myObservable = Observable.just("Hello, world!");
接下来,我们处理Subscriber中不需要的回调,在上面例子中我们只是让Observable发送一个数据,而且我们并没有覆写onComplete()和onError(),所以我们用一个简单的类定义在onNext()中做什么:
Action1<String> onNextAction = new Action1<String>() { @Override public void call(String s) { System.out.println(s); } };
Actions可以定义Subscriber的每一个动作,例如onNext(),onError,onComplete():
myObservable.subscribe(onNextAction, onErrorAction, onCompleteAction);
然而,我们只需要第一个参数,因此先忽略onError()和onComplete():
myObservable.subscribe(onNextAction); // Outputs "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(因此不能使用Java 8),我强烈推荐你使用retrolambda,它能极大了减少冗长的代码。
0x03 变换
让我们做的更有趣些。假设我想要在”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"));
这个答案也不尽人意,因为我想要Subscribers尽量的简单,Subscribers可能需要在主线程中运行。从概念层面,Subscribers应该是响应事件,而非修改事件。
那岂不是很酷,如果我可以在一些中间步骤改变“Hello, world!”?
0x04 使用变换操作符(Operators)
这里不是对RxJava所有Operators的介绍,如果需要更多的了解请移步这里下面我要解决数据变换的问题,通过介于Observable与Subscriber之间的操作符。RxJava带有大量的操作符集合,但我们目前最好只关注极少数。
对于这种情况,map()操作符可以用于变换被发射的数据:
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()操作符变换发射的数据并返回另外的Observable,我们可以链式调用map(),变换数据到Subscriber最终消费形式。
0x05 map()操作符(Operators)
map操作符有个有趣的方面,它不必返回与源Observable相同的返回类型假定我的Subscriber对输出原文本不感兴趣,而是要输出文本的哈希值:
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)));
有趣,我们开始用一个字符串,但最终我们的Subscriber收到一个整数,我们再次用lambda表达式简化这段代码:
Observable.just("Hello, world!") .map(s -> s.hashCode()) .subscribe(i -> System.out.println(Integer.toString(i)));
如我之前所说,我们希望我们的Subscriber尽可能做的更少,我们用另一个map把字符串哈希转会字符串:
Observable.just("Hello, world!") .map(s -> s.hashCode()) .map(i -> Integer.toString(i)) .subscribe(s -> System.out.println(s));
请看:我们的Observable和Subscriber都回到了他们原来的代码,我们只是增加了一些转换步骤。我们同样可以添加我的签名然后变换:
Observable.just("Hello, world!") .map(s -> s + " -Dan") .map(s -> s.hashCode()) .map(i -> Integer.toString(i)) .subscribe(s -> System.out.println(s));
0x06 那又怎样?
在这一点上,你可能认为,这些是简单的代码加入了很多花式。这时一个简单的例子,但是你应该从中获得两种理念:1.Observable和Subscriber可以做任何事情
Observable发射的事件可以来自是一个数据库查询,Subscriber用来显示查询结果;也可以来自屏幕上的点击事件,Subscriber用来响应点击事件;Observable可以是一个网络请求返回的数据流,Subscriber用来向硬盘写入结果。
这是一个可以处理任何问题的通用框架。
2.Observable和Subscriber是独立于中间的变换过程的
在Observable和Subscriber中间可以链式调用很多map操作符,该系统具有高度的可组合性:它很容易操纵数据。只要操作符数据输入输出都正确,就可以一直链式调用下去。
结合以上两个主要的想法,你可以看到一个具有很大的潜力的系统,虽然当前我们只知道map操作符,这严重限制了我们的能力。在第2部分,我们将畅游RxJava提供的大量操作符。
相关文章推荐
- springmvc学习笔记
- Java多线程——寺庙问题
- Spring mvc 配置事务的注意点
- java方法调用之单分派与多分派(二)
- [JAVA]学习笔记(三)——访问权限控制
- Spring注解
- JAVA内存模型(Java Memory Model)
- java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "javamelody jenkins
- Java 实现文章汉字关键词(违禁词)识别2.0
- maven+Spring4(restful)整合
- 双缓冲的使用—java语言
- JAVA设计模式之单例模式
- 关于在myeclipse中导入工程所遇到的问题,解决办法
- java面向对象编程杂谈
- bzoj3198 spring hash&容斥原理
- java智力拼图小游戏
- java锁的种类以及辨析
- JDBC驱动自身问题引发的FullGC
- JAVA打印二维码图片自定义高度
- JavaEE_Servlet的页面跳转 和 参数的传递