RxJava

要在Android中使用RxJava2, 先添加Gradle配置:

  1. compile 'io.reactivex.rxjava2:rxjava:2.0.1'
  2. compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

原理

在开始学习之前,先来介绍点原理性的东西。

网上也有很多介绍RxJava原理的文章,通常这些文章都从观察者模式开始,先讲观察者,被观察者,订阅关系巴拉巴拉一大堆,说实话,当我第一次看到这些文章的时候已经被这些名词给绕晕了,用了很长的时间才理清楚它们之间的关系。可能是我太蠢了,境界不够,领会不到那么多高大上的名词.

今天我用两根水管代替观察者和被观察者, 试图用通俗易懂的话把它们的关系解释清楚, 在这里我将从事件流这个角度来说明RxJava的基本工作原理。

先假设有两根水管:

上面一根水管为事件产生的水管,叫它上游吧,下面一根水管为事件接收的水管叫它下游吧。

两根水管通过一定的方式连接起来,使得上游每产生一个事件,下游就能收到该事件。注意这里和官网的事件图是反过来的, 这里的事件发送的顺序是先1,后2,后3这样的顺序, 事件接收的顺序也是先1,后2,后3的顺序, 我觉得这样更符合我们普通人的思维, 简单明了.

这里的上游下游就分别对应着RxJava中的ObservableObserver,它们之间的连接就对应着subscribe(),因此这个关系用RxJava来表示就是:

  1. //创建一个上游 Observable:
  2. Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
  3. @Override
  4. public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
  5. emitter.onNext(1);
  6. emitter.onNext(2);
  7. emitter.onNext(3);
  8. emitter.onComplete();
  9. }
  10. });
  11. //创建一个下游 Observer
  12. Observer<Integer> observer = new Observer<Integer>() {
  13. @Override
  14. public void onSubscribe(Disposable d) {
  15. Log.d(TAG, "subscribe");
  16. }
  17. @Override
  18. public void onNext(Integer value) {
  19. Log.d(TAG, "" + value);
  20. }
  21. @Override
  22. public void onError(Throwable e) {
  23. Log.d(TAG, "error");
  24. }
  25. @Override
  26. public void onComplete() {
  27. Log.d(TAG, "complete");
  28. }
  29. };
  30. //建立连接
  31. observable.subscribe(observer);

这个运行的结果就是:

  1. 12-02 03:37:17.818 4166-4166/zlc.season.rxjava2demo D/TAG: subscribe
  2. 12-02 03:37:17.819 4166-4166/zlc.season.rxjava2demo D/TAG: 1
  3. 12-02 03:37:17.819 4166-4166/zlc.season.rxjava2demo D/TAG: 2
  4. 12-02 03:37:17.819 4166-4166/zlc.season.rxjava2demo D/TAG: 3
  5. 12-02 03:37:17.819 4166-4166/zlc.season.rxjava2demo D/TAG: complete

注意: 只有当上游和下游建立连接之后, 上游才会开始发送事件. 也就是调用了subscribe() 方法之后才开始发送事件.

把这段代码连起来写就成了RxJava引以为傲的链式操作:

  1. Observable.create(new ObservableOnSubscribe<Integer>() {
  2. @Override
  3. public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
  4. emitter.onNext(1);
  5. emitter.onNext(2);
  6. emitter.onNext(3);
  7. emitter.onComplete();
  8. }
  9. }).subscribe(new Observer<Integer>() {
  10. @Override
  11. public void onSubscribe(Disposable d) {
  12. Log.d(TAG, "subscribe");
  13. }
  14. @Override
  15. public void onNext(Integer value) {
  16. Log.d(TAG, "" + value);
  17. }
  18. @Override
  19. public void onError(Throwable e) {
  20. Log.d(TAG, "error");
  21. }
  22. @Override
  23. public void onComplete() {
  24. Log.d(TAG, "complete");
  25. }
  26. });

接下来解释一下其中两个陌生的玩意:ObservableEmitterDisposable.

ObservableEmitter: Emitter是发射器的意思,那就很好猜了,这个就是用来发出事件的,它可以发出三种类型的事件,通过调用emitter的onNext(T value)onComplete()onError(Throwable error)就可以分别发出next事件、complete事件和error事件。

但是,请注意,并不意味着你可以随意乱七八糟发射事件,需要满足一定的规则:

  • 上游可以发送无限个onNext, 下游也可以接收无限个onNext.
  • 当上游发送了一个onComplete后, 上游onComplete之后的事件将会继续发送, 而下游收到onComplete事件之后将不再继续接收事件.
  • 当上游发送了一个onError后, 上游onError之后的事件将继续发送, 而下游收到onError事件之后将不再继续接收事件.
  • 上游可以不发送onComplete或onError.
  • 最为关键的是onComplete和onError必须唯一并且互斥, 即不能发多个onComplete, 也不能发多个onError, 也不能先发一个onComplete, 然后再发一个onError, 反之亦然

注: 关于onComplete和onError唯一并且互斥这一点, 是需要自行在代码中进行控制, 如果你的代码逻辑中违背了这个规则, **并不一定会导致程序崩溃. ** 比如发送多个onComplete是可以正常运行的, 依然是收到第一个onComplete就不再接收了, 但若是发送多个onError, 则收到第二个onError事件会导致程序会崩溃.

介绍了ObservableEmitter, 接下来介绍Disposable, 这个单词的字面意思是一次性用品,用完即可丢弃的. 那么在RxJava中怎么去理解它呢, 对应于上面的水管的例子, 我们可以把它理解成两根管道之间的一个机关, 当调用它的dispose()方法时, 它就会将两根管道切断, 从而导致下游收不到事件.

注意: 调用dispose()并不会导致上游不再继续发送事件, 上游会继续发送剩余的事件.

来看个例子, 我们让上游依次发送1,2,3,complete,4,在下游收到第二个事件之后, 切断水管, 看看运行结果:

  1. Observable.create(new ObservableOnSubscribe<Integer>() {
  2. @Override
  3. public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
  4. Log.d(TAG, "emit 1");
  5. emitter.onNext(1);
  6. Log.d(TAG, "emit 2");
  7. emitter.onNext(2);
  8. Log.d(TAG, "emit 3");
  9. emitter.onNext(3);
  10. Log.d(TAG, "emit complete");
  11. emitter.onComplete();
  12. Log.d(TAG, "emit 4");
  13. emitter.onNext(4);
  14. }
  15. }).subscribe(new Observer<Integer>() {
  16. private Disposable mDisposable;
  17. private int i;
  18. @Override
  19. public void onSubscribe(Disposable d) {
  20. Log.d(TAG, "subscribe");
  21. mDisposable = d;
  22. }
  23. @Override
  24. public void onNext(Integer value) {
  25. Log.d(TAG, "onNext: " + value);
  26. i++;
  27. if (i == 2) {
  28. Log.d(TAG, "dispose");
  29. mDisposable.dispose();
  30. Log.d(TAG, "isDisposed : " + mDisposable.isDisposed());
  31. }
  32. }
  33. @Override
  34. public void onError(Throwable e) {
  35. Log.d(TAG, "error");
  36. }
  37. @Override
  38. public void onComplete() {
  39. Log.d(TAG, "complete");
  40. }
  41. });

运行结果为:

  1. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: subscribe
  2. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 1
  3. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: onNext: 1
  4. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 2
  5. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: onNext: 2
  6. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: dispose
  7. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: isDisposed : true
  8. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 3
  9. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit complete
  10. 12-02 06:54:07.728 7404-7404/zlc.season.rxjava2demo D/TAG: emit 4

从运行结果我们看到, 在收到onNext 2这个事件后, 切断了水管, 但是上游仍然发送了3, complete, 4这几个事件, 而且上游并没有因为发送了onComplete而停止. 同时可以看到下游的onSubscribe()方法是最先调用的.

Disposable的用处不止这些, 后面讲解到了线程的调度之后, 我们会发现它的重要性. 随着后续深入的讲解, 我们会在更多的地方发现它的身影.

另外, subscribe()有多个重载的方法:

  1. public final Disposable subscribe() {}
  2. public final Disposable subscribe(Consumer<? super T> onNext) {}
  3. public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {}
  4. public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
  5. public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
  6. public final void subscribe(Observer<? super T> observer) {}

最后一个带有Observer参数的我们已经使用过了,这里对其他几个方法进行说明.

  • 不带任何参数的subscribe() 表示下游不关心任何事件,你上游尽管发你的数据去吧, 老子可不管你发什么.
  • 带有一个Consumer参数的方法表示下游只关心onNext事件, 其他的事件我假装没看见, 因此我们如果只需要onNext事件可以这么写:
  1. Observable.create(new ObservableOnSubscribe<Integer>() {
  2. @Override
  3. public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
  4. Log.d(TAG, "emit 1");
  5. emitter.onNext(1);
  6. Log.d(TAG, "emit 2");
  7. emitter.onNext(2);
  8. Log.d(TAG, "emit 3");
  9. emitter.onNext(3);
  10. Log.d(TAG, "emit complete");
  11. emitter.onComplete();
  12. Log.d(TAG, "emit 4");
  13. emitter.onNext(4);
  14. }
  15. }).subscribe(new Consumer<Integer>() {
  16. @Override
  17. public void accept(Integer integer) throws Exception {
  18. Log.d(TAG, "onNext: " + integer);
  19. }
  20. });

RxJava的学习与实现的更多相关文章

  1. [RxJava]在学习RxJava中的错误理解

    关于RxJava语法的问题与理解   最近看到一个blog-RxJava 写到关于Observable数据异步加载的介绍.针对fromCallable和just操作符在使用上的问题来跟大家针对代码进行 ...

  2. rxJava rxandroid 学习

    学习地址 很全面: http://blog.csdn.net/meegomeego/article/details/49155989 final String[] words = {"Hel ...

  3. 开源库RxJava、ButterKnife学习记录

    1. 简介 RxJava "RxJava is a Java VM implementation of Reactive Extensions: a library for composin ...

  4. 我的Android进阶之旅------>RxJava学习资料汇总

    在响应式编程中,应该牢记以下两点: everything is a stream(一切皆流) don't break the chain(不要打断链式结构) 记住,可观测序列就像一条河,它们是流动的. ...

  5. 开源库RxJava、ButterKnife

    1. 简介 RxJava "RxJava is a Java VM implementation of Reactive Extensions: a library for composin ...

  6. 优雅地使用Retrofit+RxJava(二)

    前言 在我上一篇讲Retrofit+RxJava在MVP模式中优雅地处理异常(一)中,发现非常多网友发邮箱给我表示期待我的下一篇文章,正好趁着清明假期.我就写写平时我在使用RxJava+Retrofi ...

  7. RxJava——响应式编程

    自从06年开始,Rxandroid公司项目中陆续就开始使用它了,而它的基础是由Rxjava演变过来的,如今它也是越来越被广泛使用在商业项目中了,而做为"专业"的自己还是一直对它一知 ...

  8. 学习响应式编程 Reactor (1) - 响应式编程

    响应式编程 命令式编程(Imperative Programing),是一种描述计算机所需做出的行为的编程范式.详细的命令机器怎么(How)去处理以达到想要的结果(What). 声明式编程(Decla ...

  9. Rxjava2视频笔记

    观察者模式 观察者模式是一对多的模式,多个观察者同时监听一个主题,当主题更新时,会同时通知所有的观察者 subject –>observer 学习新技术的步骤 1.官方文档的查阅和学习 2.Go ...

随机推荐

  1. linux--mysql的安装与配置

    linux centos下,mysql安装有三种方式:二进制tar包安装,rpm安装,yum安装(最简单) 查看有没有安装过: yum list installed mysql* rpm -qa | ...

  2. 解决python中转化成json的方法不能序列化datetime类型数据(转)

    Python自带的json.dumps方法序列化数据时候如果格式化的数据中有datetime类型数据时候会提示错误TypeError: datetime.datetime(2012, 12, 12, ...

  3. Kotlin学习笔记(9)- 数据类

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步! Kotlin学习笔记(1)- 环境配置 Kotlin学习笔记(2)- 空安 ...

  4. mysql,分组后,再次进行过滤

    查出平均分大于80以上的班级 select class_id, avg(score) from students group by class_id having avg(score)>80;  ...

  5. UVA11540 Sultan's Chandelier Burnside 引理 + DP

    题目传送门 https://vjudge.net/problem/UVA-11540 https://uva.onlinejudge.org/index.php?option=com_onlineju ...

  6. hibernate 5原生sql查询测试学习代码

    基本查询 import java.util.List; import org.hibernate.SQLQuery; import org.hibernate.Session; import org. ...

  7. springBoot 连接数据库

    心得:1.先添加依赖. 2.在application.yml文件中创建mybatis的连接,与项目连接起来. 3.application.yml文件中可以自行配置服务器的端口,配置mybatis的路径 ...

  8. map简单用法

    let familyNames = []; familyNames = res.Data.map(item=> { return item.ArgText });

  9. mybatis框架之装饰模式

    学习开源框架源码,除了储备点知识以便于与面试官互相忽略之外,我想最重要的还是去学习大神如何写代码,如何做到职责单一,如何做到可扩展等... 本篇,试着总结一下mybatis在缓存模块使用到的装饰模式. ...

  10. spring-boot的helloWorld详解

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 3.2.5 2.Maven Plugin管理 pom.xml配置代码: <project xml ...