RxJava 2.x.x Observable 与 Observer 入门分析
来源:互联网 发布:涌泉知恩 编辑:程序博客网 时间:2024/05/22 05:11
概要
RxJava 是响应式扩展(Reactive Extension) 在 Java 和 Android 上的实现。 RxJava 以观察者模式为基础,扩展大量的操作符,解决了异步或基于事件驱动的编程问题。
Observable
Observable< T > 代表数据或者事件的流,在 Android 中,当你多次点击一个 Button 的时候就会产生一个点击事件流。
Observable< T > 通过调用 ObservableEmitter 的方法可以产生三种类型的事件:
- ObservableEmitter.onNext(),用来发送类型为 T 的数据
- ObservableEmitter.onComplete(),完成事件,是一个终止事件
- ObservableEmitter.onError(),错误事件,也是一个终止事件
onNext() 是发送事件,Observable 可以发送 0 个,1 个,甚至无限个事件。 而 onError() 和 onComplete() 是终止事件,有且只能有一个出现,当终止事件发生后,也就不会再有事件发送了。
订阅 Observable 事件
虽然 Observable 有发送事件的能力,但是仅仅只拥有 Observable 对象是不会发送任何事件的,现在来创建一个 Observable 对象
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception { Log.d(TAG, "onNext(1)"); e.onNext(1); Log.d(TAG, "onNext(2)"); e.onNext(2); Log.d(TAG, "onComplete()"); e.onComplete(); } });
这个匿名内部类对象太长了,用 Lambda 表达式简化下
// create observable instance Observable<Integer> observable = Observable.create(e -> { Log.d(TAG, "onNext(1)"); e.onNext(1); Log.d(TAG, "onNext(2)"); e.onNext(2); Log.d(TAG, "onComplete()"); e.onComplete(); });
运行上面代码,不会看到任何 Log 信息。 因为只有当 Observable 对象被订阅了,Observable 对象才会产生事件
// subscribe observable, only receive events, but do nothing observable.subscribe();
那么现在运行代码,可以看到 Log 信息了。
然而,这个订阅的方式却相当的奇怪,居然是用 Observable 对象来调用订阅方法 subscribe(),我想应该是为了方便函数式调用
Observable.create(e -> e.onNext(1)).subscribe();
这样看起来是不是就很简洁呢?
然而,我们发现一个问题 ,observable.subscribe()
订阅后,虽然产生了事件,但是我们并没有处理事件。那么怎么处理事件呢,我想你一定会猜到向 subscribe() 方法里传入参数来处理事件,俗称 Callback。
通过查看,可以发现 subscribe() 方法有5个重载的方法,如截图所示。
这些重载方法都是有规律可循的,先来看只有一个参数的方法。
observable.subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { } });
从截图中看这个参数的命名,你应该猜到第一个 Callback 是处理 onNext() 事件的,现在我们用 Lambda 表达式来简化下,后面的我讲都用 Lambda 表达式简化代码
// subscribe observable , only receive onNext() event observable.subscribe(integer -> Log.d(TAG, "integer = " + integer));
再运行代码的时候,就可以看到处理 onNext() 事件的的 Log 了。
从截图中可以看出,第二个参数名为 onError,也就是处理 onError() 事件,那么为什么会有 onError() 事件?
因为 Observable 不会抛出异常,然而如果有异常发生,Observable 会发送一个通知事件,这个事件就是 onError(),因此你不必用 try-catch 代码块包含 subscribe() 方法来捕获异常,而你需要做的就是提供一个回调来接收 onError() 事件,这就是 subscribe() 方法的第二个参数的用法。
还有一个总是,我们是否需要关心 onComplete() 事件?
对于一个无限流来说,接收 onComplete() 事件是无意义的,而对于一个有限流来说,是否需要接收 onComplete() 事件还要取决于 Subscriber。例如,如果我用 Observable< Progress > 来监测文件的下载进度,其实中间的过程我们并不在意,而我们真正在意的是这个文件什么时候下载成功,也就是什么时候接收 onComplete() 事件。
这次索性直接看三个参数的方法
// subscribe observable , receive onNext, onError, onComplete events observable.subscribe( integer -> Log.d(TAG, "integer = " + integer), throwable -> Log.d(TAG, "error!!!"), () -> Log.d(TAG, "complete!!"));
运行代码后,只能看到处理的 onNext, onComplete 事件,因为 Observable 对象没有发送 onError 事件,然而一定要记住,onComplete 和 onError 事件是能出现其中一个。
如果对 subscribe() 参数不熟悉,可以先创建匿名内部类对象,再转化为 Lambda 表达式
最后看看四个参数的 subscribe() 方法
// subscribe observable , receive all events observable.subscribe( integer -> Log.d(TAG, "integer = " + integer), throwable -> Log.d(TAG, "error!!!"), () -> Log.d(TAG, "complete!!"), disposable -> Log.d(TAG, "disposable!!"));
disposable 翻译为一次性的东西,尤其指容器,这里可以理解为一个管道,连通 Observable 的管道。从上面截图中可以看出,最后一个参数叫 onSubscribe,代表订阅成功后的 Callback,与 onClickListener 中的 onClick 回调方法有异曲同工之妙。
运行下代码看看 Log 信息
david: disposable!!david: onNext(1)david: integer = 1david: onNext(2)david: integer = 2david: onComplete()david: complete!!
从Log中看,首先要成功建立订阅关系,然后才能发送事件。
现在,我们知道如何订阅 Observable 对象,如何处理事件,但是处理事件的时候,几个参数写的有点麻烦,怎么办呢,把这几个回调方法封装到一起,就成为了我们熟悉的 Observer< T > 接口了,现在来创建一个 Observer 对象
Observer<Integer> observer = new Observer<Integer>() { @Override public void onSubscribe(@NonNull Disposable d) { } @Override public void onNext(@NonNull Integer integer) { } @Override public void onError(@NonNull Throwable e) { } @Override public void onComplete() { } };
perfect! 创建完 Observer 对象,剩下就是订阅了
observable.subscribe(observer);
这就是 subscribe() 方法的最后一个重载方法了。
最后用一个函数式编程风格代码来做个总结
Observable.create((ObservableOnSubscribe<Integer>) e -> { e.onNext(1); e.onNext(2); e.onComplete(); }).subscribe(new Observer<Integer>() { @Override public void onSubscribe(@NonNull Disposable d) { } @Override public void onNext(@NonNull Integer integer) { } @Override public void onError(@NonNull Throwable e) { } @Override public void onComplete() { } });
控制订阅关系
我们知道 Observable 对象可以发送任意数量的 onNext 事件
private int i; Observable.create((ObservableOnSubscribe<Integer>) e -> { while (true) { e.onNext(i++); } })
但是 Observer 对象订阅 Observerable 对象后,并不想处理所有的 onNext 事件,那就只能取消订阅关系,我们可以用 Disposal 对象调用 dispose() 方法取消订阅。
Disposable
Disposal 对象取消订阅的方式分为两种,一种是外部取消,一种是内部取消。
内部取消订阅,我们用给 Observable.subscribe() 传入 Observer 对象举例
private int i; Observable.create((ObservableOnSubscribe<Integer>) e -> { while (true) { e.onNext(i++); } }).subscribe(new Observer<Integer>() { private Disposable mDisposable; @Override public void onSubscribe(@NonNull Disposable d) { mDisposable = d; } @Override public void onNext(@NonNull Integer integer) { Log.d(TAG, "integer = " + integer); if (integer == 100 && !mDisposable.isDisposed()) { mDisposable.dispose(); } } @Override public void onError(@NonNull Throwable e) { } @Override public void onComplete() { } });
从代码中可以看出,在 onSubscribe() 方法中,我们可以获取到 Dispoasble 对象 d(我称之为管道),然后在 onNext() 方法中,如果这个 integer 值等于 100 了 , 并且管道 d 还没有被切断,那么就切断管道。 这样一来,就不会再接收事件了,也就是说 100 之后的数据就不再有了。
那么 Observable.subscribe() 的四个参数的重载方法切断管道的原理也就是类似了。
private int i; private Disposable mDisposable; Observable.create((ObservableOnSubscribe<Integer>) e -> { while (true) { e.onNext(i++); } }).subscribe( integer -> { if (integer == 999 && !mDisposable.isDisposed()) { mDisposable.dispose(); } Log.d(TAG, "integer = " + integer); }, throwable -> Log.d(TAG, "error"), () -> Log.d(TAG, "complete"), disposable -> mDisposable = disposable );
那怎么用 Disposal 对象外部取消订阅呢? 其实如果 Observerable.subscribe() 方法传入的不是 Observer 对象,那么可以生成 Disposal 对象
Disposable d = Observable.create((ObservableOnSubscribe<Integer>) e -> { while (true) { e.onNext(1); e.onNext(2); e.onNext(3); } }).subscribe( integer -> Log.d(TAG, "integer = " + integer) );
获取到 Disposal 对象 d 后,就可以来取消订阅了
d.dispose();
如果 Observerable.subscribe() 方法传入的是 Observer 对象,那么是没有返回值的,因为 Observer 对象本身就可以获取到 Disposable 对象,如果再返回,岂不是多此一举。
然而,当我们运行程序后发现,却发现Observerable 对象发送的事件并没有在停止,why? 因为这个 Observerable 发送事件是在主线程中的,所以 d.dispose() 并没有执行。如果要想从外面取消订阅,这个 Observerable 不能运行在主线程中,当然这是后话了。
总结
本篇文章主要是对 RxJava 有个大致的理解,并对 Observable 和 Observer 稍作分析,当做 RxJava 2.x.x 的一个入门吧。
- RxJava 2.x.x Observable 与 Observer 入门分析
- RxJava 1.x Observable分析
- Observable与Observer
- Observable与Observer
- Observable与Observer
- Observable与Observer
- Observer与Observable
- Observer与Observable
- Observer与Observable
- Observer与Observable
- Observer与Observable关系
- Observable与Observer
- 体会 Observable与Observer 模式
- Observable与Observer (观察者模式)
- RxJava 2.x入门教程
- Android RxJava 2.x入门例子详解(一)
- Android RxJava 2.x入门例子详解(二)
- Android RxJava 2.x入门例子详解(三)
- Java NIO 详解(二)
- 二维树状数组(bzoj 1452: [JSOI2009]Count)
- Steering Behaviors
- PHP Database ODBC
- 基于erlang语言的socket通信
- RxJava 2.x.x Observable 与 Observer 入门分析
- Mycat读写分离与注意事项
- Oauth详解
- java多线程获取结果 Callable和Future
- 排序算法一——冒泡排序
- zoj3710 friends(floyd变形)
- XML
- 套路数学——扫雷
- 浅谈JVM内存模型