RxJava2
这篇只适合 Android 开发者 RxJava 初次食用
放上官方文档, 如果想自己透彻的了解, 还是要翻一翻官方文档
凯哥的教程由于是基于 RxJava1 的版本, 在使用上可能会有点区别, 如果看的有点晕就瞅瞅我下面写的吧.
首先加入依赖:
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
// Because RxAndroid releases are few and far between, it is recommended you also
// explicitly depend on RxJava's latest version for bug fixes and new features.
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
1. 创建和订阅事件
首先理清两个概念:
- Observe 观察者
- Observable 被观察者
一个观察者(Observer)订阅一个可观察对象(Observable), 观察者对Observable发射的数据或数据序列作出响应。这就是 响应式编程(reactive pattern)
创建一个观察者Observe
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
// 可以在此处进行取消订阅的操作
}
@Override
public void onNext(String s) {
// 这里传入被观察者传入的数据
}
@Override
public void onError(Throwable e) {
// 处理被观察者的异常
}
@Override
public void onComplete() {
// 被观察者完成任务后被调用
}
};
创建我们的被观察者Observable
创建的方式有很多种:Create, Defer, Empty/Never/Throw, From, Interval, Just, Range, Repeat, Start, and Timer
我们就用简单的 Create ,Just,FromArray 来做下说明
just代表了传入一系列
简单的 Create 创建需要复写subscribe方法,并手动调用 emitter.onNext() , onError 和 onComplete
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
try {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
}
});
-
onNext(T item)
Observable调用这个方法发射数据,方法的参数就是Observable发射的数据,这个方法可能会被调用多次,取决于你的实现。
-
onError(Exception ex)
当Observable遇到错误或者无法返回期望的数据时会调用这个方法,这个调用会终止Observable,后续不会再调用onNext和onCompleted,onError方法的参数是抛出的异常。
-
onComplete
正常终止,如果没有遇到错误,Observable在最后一次调用onNext之后调用此方法。
注意 :
- onComplete 和 onError 可以不调用
- onNext 可以被调用多次
- 传递数据被称为发射,onComplete 和 onError 一般只是通知
产生订阅
observable.subscribe(observer);
一行,是不是很简单?对的,这样就完成了订阅
当然,这肯定不是唯一的订阅模式。
如果你的被观察者想要自己消费掉自己的下游事件,当然也是可行的。
Observable.just(1, 2, 3, 4)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "accept: " + integer);
}
});
捕获异常?事件完成提醒?OK!
Observable.just(1, 2, 3, 4)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d(TAG, "accept: " + integer);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
// 处理异常
}
}, new Action() {
@Override
public void run() throws Exception {
// onComplete
}
});
2. 线程调度器
其中一个我特别喜欢 RxJava2 的理由就是在线程的切换方面无比的方便和逻辑清晰

mService.getUserInfo("token")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<UserInfo>() {
@Override
public void accept(UserInfo userInfo) throws Exception {
// 主线程进行 Ui 操作
}
});
通过两个操作符,当然你还不知道操作符为何物,稍微介绍一下,通过使用操作符可以改变一些状态。
这里你就把observeOn() 和 subscribeOn() 理解为用来切换执行线程的操作符
observeOn(Scheduler scheduler)
很多ReactiveX实现都使用调度器 "Scheduler"来管理多线程环境中Observable的转场。你可以使用ObserveOn操作符指定Observable在一个特定的调度器上发送通知给观察者 (调用观察者的onNext, onCompleted, onError方法)。

注意:当遇到一个异常时
ObserveOn会立即向前传递这个onError终止通知,它不会等待慢速消费的Observable接受任何之前它已经收到但还没有发射的数据项。这可能意味着onError通知会跳到(并吞掉)原始Observable发射的数据项前面,正如图下展示的。

这个observeOn()如何理解呢,这里我要推荐一下知乎之前搞得分析,讲的已经很清晰了,贴上地址zhihu-rxjava-meetup,非常感谢
杨凡的栗子举的非常好。将每一个observeOn()当场一个弹球的挡板。
每在一个链式调用一个observeOn() 时,就相当于把之前的操作和挡板之后的操作分离开了。挡板之后的操作到下一块挡板所在的线程(不止可以设一个挡板),就是我们 observeOn() 指定的线程。
subscribeOn()
subscribeOn() 表示呢,调度的是最上游到第一块挡板之间的操作,并且只取最上游的那一个。
祭出一张图

每一块调度器呢都是一个三角块,小箭头的颜色代表着当前任务的线程,图中的又长又粗的箭头,代表着
它的作用域。
但是对于这样一个使用方式,刚刚的结论就不再适用了。

如果按照刚刚那样分析的话,A() 跑在主线程,B( ), C( ) D( )跑在 IO 线程,但是真的是这样吗?不是

这确是实际上的操作模式,为什么会这样呢
就是因为 flatmap 操作符,实际是切换 Observable 的操作,可以理解为从一个上游切换到另一个上游。这样就把 flatmap 后面的操作执行在主线程上了。类似的操作符还有,deff( ) ,onErrorResumeNext( )
如果我们把 subscribeOn( ) 从 flatmap 里面拿出来,那么就可以按照之前的挡板法去解释,具体看图。

如果想要写出更清晰的代码,我们应该遵循以下两点:
- 尽量多用 observerOn()
- 保证流里只有一个subscribeOn( ),放在越前面越好
参考:
操作符?map,flatmap傻傻分不清?后面这篇文章让你彻底清晰