第二章 RxJava基础知识

1. Observable

1.1 RxJava的使用三步骤

  1. 创建Observable
  2. 创建Observer
  3. 使用subscribe()进行订阅
Observable.just("Hello World")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});

subscribe()有多个重载方法:

Disposable subscribe()

Disposable subscribe(Consumer<? super T> onNext)

Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)

Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete) Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete, Consumer<? super Disposable> onSubscribe) void subscribe(Observer<? super T> observer)

Consumer是消费者。

onComplete是一个Action,它与Consumer的区别如下:

  • Action:无参数
  • Consumer:单一参数类型

第五种重载例子:

Observable.just("Hello World")
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
System.out.println(throwable.getMessage());
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("onComplete");
}
}, new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("subscribe");
}
});
执行结果:
subscribe
Hello World
onComplete

Rxjava2中,Observable不在支持Subscriber,而是需要使用Observer作为观察者。

 Observable.just("Hello World")
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
} @Override
public void onNext(String s) {
System.out.println(s);
} @Override
public void onError(Throwable e) {
System.out.println(e.getMessage());
} @Override
public void onComplete() {
System.out.println("onComplete");
}
}); 执行结果:
onSubscribe
Hello World
onComplete

在Rxjava中,被观察者、观察者、subscribe()方法三者缺一不可。只有使用了subscribe(),被观察者才会开始发送数据。

1.2 RxJava2的五种观察者模式:

类型 描述
Observable 能够发射0或n个数据,并以成功或者错误事件终止
Flowable 能够发射0或n个数据,并以成功或者错误事件终止。支持背压,可以控制数据源发射的速度
Single 只发射单个数据或者错误事件
Completable 从来不发射数据,只处理onComplete和onError事件。可以看成Rx的Runnable
Maybe 能够发射0或者1个数据,要么成功,要么失败。有点类似于Optional

5种被观察者类型中只有Flowable支持背压。

1.3 do操作符

操作符 用途
doOnSubscribe 一旦观察者订阅了Observable,它就会被调用
doOnLifecycle 可以在观察者订阅之后,设置是否取消订阅
doOnNext 它产生的Observable每发射一项数据就会调用它一次,它的Consumer接受发射的数据项。一般用于在subscribe之前对数据进行处理
doOnEach 它产生的Observable每发射一项数据就会调用它一次,不仅包括onNext,还包括onError和onComplete
doAfterNext 在onNext之后执行,而doOnNext()是在onNext之前执行
doOnComplete 当产生的Observable在正常终止调用onComplete时会被调用
doFinally 在当它产生的Observable终止之后会被调用,无论是正常终止还是异常终止。doFinally优先于doAfterTerminate的调用
doAfterTerminate 注册一个Action,当Observable调用onComplete或onError时调用
 public static void main(String[] args) {
Observable.just("Hello World")
.doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doOnNext:"+s);
}
}).doAfterNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doAfterNext:"+s);
}
}).doOnComplete(new Action() {
@Override
public void run() throws Exception {
System.out.println("doOnComplete");
}
}).doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("doOnSubscribe:"); }
}).doAfterTerminate(new Action() {
@Override
public void run() throws Exception {
System.out.println("doAfterTerminate:");
}
}).doOnEach(new Consumer<Notification<String>>() {
@Override
public void accept(Notification<String> stringNotification) throws Exception {
System.out.println("doOnEach:"+(stringNotification.isOnNext()?"onNext":stringNotification.isOnComplete()?"onComplete":"onError")+" value:"+stringNotification.getValue());
}
}).doFinally(new Action() {
@Override
public void run() throws Exception {
System.out.println("doFinally:");
}
}).doOnLifecycle(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
System.out.println("doOnLifecycle:"+disposable.isDisposed());
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("doOnLifecycle: run");
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe:");
} @Override
public void onNext(String s) {
System.out.println("onNext:"+s);
} @Override
public void onError(Throwable e) {
System.out.println("onError:"+e.getMessage());
} @Override
public void onComplete() {
System.out.println("onComplete:");
}
}); 执行结果:
doOnSubscribe:
doOnLifecycle:false
onSubscribe:
doOnNext:Hello World
doOnEach:onNext value:Hello World
onNext:Hello World
doAfterNext:Hello World
doOnComplete
doOnEach:onComplete value:null
onComplete:
doFinally:
doAfterTerminate:

doOnEach与doOnNext、doOnComplete()、doOnError执行顺序:谁在前面先执行谁。

doOnEach放到doOnNext上面执行:

        ...
.doOnEach(new Consumer<Notification<String>>() {
@Override
public void accept(Notification<String> stringNotification) throws Exception {
System.out.println("doOnEach:"+(stringNotification.isOnNext()?"onNext":stringNotification.isOnComplete()?"onComplete":"onError")+" value:"+stringNotification.getValue());
}
}).doOnNext(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("doOnNext:"+s);
}
})... 执行结果: doOnSubscribe:
doOnLifecycle:false
onSubscribe:
doOnEach:onNext value:Hello World
doOnNext:Hello World
onNext:Hello World
doAfterNext:Hello World
doOnEach:onComplete value:null
doOnComplete
onComplete:
doFinally:
doAfterTerminate:

2.HotObservable和Cold Observable

2.1 Observabel分类

Observable 有 Cold 和 Hot 之分。

Hot Observable 无论有没有 Subscriber 订阅,事件始终都会发生。当 Hot Observable 有多个订阅者时,Hot Observable 与订阅者们的关系是一对多的关系,可以与多个订阅者共享信息。

Cold Observable是 只有 Subscriber 订阅时,才开始执行发射数据流的代码。并且 Cold Observable 和 Subscriber 只能是一对一的关系,当有多个不同的订阅者时,消息是重新完整发送的。也就是说对 Cold Observable 而言,有多个Subscriber的时候,他们各自的事件是独立的。

2.2 Cold Observable

Observable 的 just、creat、range、fromXXX 等操作符都能生成Cold Observable。

        Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
}; Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
}; Observable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()); observable.subscribe(subscriber1);
observable.subscribe(subscriber2); try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}

执行结果:

subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
subscriber1: 2
subscriber2: 2
subscriber2: 3
subscriber1: 3
subscriber1: 4
subscriber2: 4
subscriber2: 5
subscriber1: 5
subscriber1: 6
subscriber2: 6
subscriber1: 7
subscriber2: 7
subscriber1: 8
subscriber2: 8
subscriber1: 9
subscriber2: 9

可以看出,subscriber1 和 subscriber2 的结果并不一定是相同的,二者是完全独立的。

尽管 Cold Observable 很好,但是对于某些事件不确定何时发生以及不确定 Observable 发射的元素数量,那还得使用 Hot Observable。比如:UI交互的事件、网络环境的变化、地理位置的变化、服务器推送消息的到达等等。

2.3 Clod Observable转Hot Observable

1. 使用publish,生成ConnectableObservable

使用 publish 操作符,可以让 Cold Observable 转换成 Hot Observable。它将原先的 Observable 转换成 ConnectableObservable。

        Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
}; Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
}; Consumer<Long> subscriber3 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber3: "+aLong);
}
}; ConnectableObservable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()).publish();
observable.connect(); observable.subscribe(subscriber1);
observable.subscribe(subscriber2); try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
} observable.subscribe(subscriber3); try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}

注意,生成的 ConnectableObservable 需要调用connect()才能真正执行。

执行结果:

subscriber1: 0
subscriber2: 0
subscriber1: 1
subscriber2: 1
subscriber1: 2
subscriber2: 2
subscriber3: 2
subscriber1: 3
subscriber2: 3
subscriber3: 3
subscriber1: 4
subscriber2: 4
subscriber3: 4
subscriber1: 5
subscriber2: 5
subscriber3: 5
subscriber1: 6
subscriber2: 6
subscriber3: 6
subscriber1: 7
subscriber2: 7
subscriber3: 7
subscriber1: 8
subscriber2: 8
subscriber3: 8
subscriber1: 9
subscriber2: 9
subscriber3: 9
subscriber1: 10
subscriber2: 10
subscriber3: 10
subscriber1: 11
subscriber2: 11
subscriber3: 11

可以看到,多个订阅的 Subscriber 共享同一事件。

在这里,ConnectableObservable 是线程安全的。

2. 使用Subject/Processor

Subject 和 Processor 的作用是相同的。Processor 是 RxJava2.x 新增的类,继承自 Flowable 支持背压控制。而 Subject 则不支持背压控制。

        Consumer<Long> subscriber1 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println("subscriber1: "+aLong);
}
}; Consumer<Long> subscriber2 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber2: "+aLong);
}
}; Consumer<Long> subscriber3 = new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong) throws Exception {
System.out.println(" subscriber3: "+aLong);
}
}; Observable<Long> observable = Observable.create(new ObservableOnSubscribe<Long>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Long> e) throws Exception {
Observable.interval(10, TimeUnit.MILLISECONDS,Schedulers.computation())
.take(Integer.MAX_VALUE)
.subscribe(e::onNext);
}
}).observeOn(Schedulers.newThread()); PublishSubject<Long> subject = PublishSubject.create();
observable.subscribe(subject); subject.subscribe(subscriber1);
subject.subscribe(subscriber2); try {
Thread.sleep(20L);
} catch (InterruptedException e) {
e.printStackTrace();
} subject.subscribe(subscriber3); try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}

执行结果跟上面使用 publish 操作符是一样的。

Subject 既是 Observable 又是 Observer(Subscriber)。

当 Subject 作为 Subscriber 时,它可以订阅目标 Cold Observable 使对方开始发送事件。同时它又作为Observable 转发或者发送新的事件,让 Cold Observable 借助 Subject 转换为 Hot Observable。

注意,Subject 并不是线程安全的,如果想要其线程安全需要调用toSerialized()方法。(在RxJava1.x的时代还可以用 SerializedSubject 代替 Subject,但是在RxJava2.x以后SerializedSubject不再是一个public class)

然而,很多基于 EventBus 改造的 RxBus 并没有这么做,包括我以前也写过这样的 RxBus

RxJava2实战--第二章 RxJava基础知识的更多相关文章

  1. (转)JAVA AJAX教程第二章-JAVASCRIPT基础知识

    开篇:JAVASCRIPT是AJAX技术中不可或缺的一部分,所以想学好AJAX以及现在流行的AJAX框架,学好JAVASCRIPT是最重要的.这章我给大家整理了一些JAVASCRIPT的基础知识.常用 ...

  2. 第二章 Java基础知识(下)

    2.1.分支结构(if.switch) 2.1.1.if语句 格式一: if (关系表达式) { 语句体; } 流程一: ①首先计算关系表达式的值 ②如果关系表达式的值为true就执行语句体 ③如果关 ...

  3. 第二章 Java基础知识(上)

    2.1.注释 单行注释 // 注释内容 多行注释 /* 注释内容 */ 文档注释 /**注释内容 */ 2.2.关键字 定义:在Java语言中被赋予特殊含义的小写单词 分类: 2.3.标识符 定义:标 ...

  4. #Spring实战第二章学习笔记————装配Bean

    Spring实战第二章学习笔记----装配Bean 创建应用对象之间协作关系的行为通常称为装配(wiring).这也是依赖注入(DI)的本质. Spring配置的可选方案 当描述bean如何被装配时, ...

  5. java面向对象编程——第二章 java基础语法

    第二章 java基础语法 1. java关键字 abstract boolean break byte case catch char class const continue default do ...

  6. UNIX环境高级编程--第一章 UNIX基础知识

    第一章 UNIX基础知识 1.2 UNIX体系结构   从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...

  7. 《C#从现象到本质》读书笔记(一)第1章 .NET基础知识

    最近根据博客园大神的推荐,买了本<C#从现象到本质>.做一点读书笔记. 由于不懂IL和ildasm,winddg,太深奥,理解不了,就牛嚼草一样,先总结第一遍读书,自己总结的知识点了.不知 ...

  8. RxJava2实战--第八章 RxJava的背压

    RxJava2实战--第八章 RxJava的背压 1 背压 在RxJava中,会遇到被观察者发送消息太快以至于它的操作符或者订阅者不能及时处理相关的消息,这就是典型的背压(Back Pressure) ...

  9. 第二章----python基础

    概要:python是一种计算机编程语言,有自己的一套语法,编译器或者解释器负责把符合语法的程序代码翻译成CPU能识别的机器码,然后执行.python使用缩进来组织代码块,Python程序中大小写是敏感 ...

随机推荐

  1. C++中虚函数的作用和虚函数的工作原理

    1 C++中虚函数的作用和多态 虚函数: 实现类的多态性 关键字:虚函数:虚函数的作用:多态性:多态公有继承:动态联编 C++中的虚函数的作用主要是实现了多态的机制.基类定义虚函数,子类可以重写该函数 ...

  2. 自动化测试 selenium 测试软件安装

      一.自动化测试优点 1.对程序的回归测试更方便.在程修改的比较平凡的时候,表现的更明显. 2.可以代替测试人员运行更繁琐的测试,也可以代替测试人员不可能完成的操作(比如连续点击50次) 3.更好的 ...

  3. 22_7mybaits注解开发

    这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了. 1.常用注解说明 @Insert:实现新增 @Update:实现更新 @Dele ...

  4. 热门前沿知识相关面试问题-android插件化面试问题讲解

    插件化由来: 65536/64K[技术层面上]随着代码越来越大,业务逻辑越来繁杂,所以很容易达到一个65536的天花板,其65536指的是整个项目中的方法总数如果达到这个数量时则不无法创建新的方法了, ...

  5. bom操作,事件与jquery

    BOM操作中 window关键字 可以不写 DOM操作 学习如何查找节点 如何查找标签 选择器 事件 当符合某个条件下 自动触发的动作/响应 js绑定事件的方式 方式1 不推荐使用 <butto ...

  6. CentOS下安装libjpeg库及编译GD库

    GD库明明安装了,可处理图片的时候还是报错 Fatal error: Call to undefined function imagecreatefromjpeg() .PHP安装后,默认的gd库不支 ...

  7. 3dmax 欢迎页卡住

    C:\Program Files (x86)\Autodesk\3ds Max 9\stdplugs\dxplugins\dxDDS.mbi,把dxDDS.mbi重命名就OK了,只不过会提示他加载错误 ...

  8. Java_GUI小游戏--贪吃蛇

    贪吃蛇游戏:是一条蛇在封闭围墙里,围墙里随机出现一个食物,通过按键盘四个光标键控制蛇向上下左右四个方向移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或 ...

  9. 黑马vue---13、事件修饰符的介绍

    黑马vue---13.事件修饰符的介绍 一.总结 一句话总结: .stop 阻止冒泡:input type="button" value="戳他" @click ...

  10. SQLSTATE[HY000] [2002] Connection refused

    //域名绑定到模块 '__domain__' => [ 'admin' => 'admin', 'post' => 'api', 'user' => 'index', 'www ...