从以下几个问题来认识RxJava
异步,一个在java vm上使用可观察的序列来组成的异步,基于事件的程序库。
简洁。逻辑性强。
RxJava采用观察者模式设计,主要核心类有以下几个
Observable ->被观察者
Observer ->观察者
Subscribe ->订阅事件
关系:Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。
注意:
与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() / onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。
● onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的onNext() 发出时,需要触发 onCompleted() 方法作为标志。
● onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
● 在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。
大致图片如下:
1. 创建观察者Observer,它决定事件触发后有哪些行为。实现接口方法如下:
Observer observer = new Observer() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
在RxJava中还有一个实现的抽象类Subscriber订阅者,实现方法如下
Subscriber subscriber = new Subscriber() {
@Override
public void onNext(String s) {
Log.d(tag, "Item: " + s);
}
@Override
public void onCompleted() {
Log.d(tag, "Completed!");
}
@Override
public void onError(Throwable e) {
Log.d(tag, "Error!");
}
};
Observer 和 Subscriber 它们的区别主要有两点:
1). onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始, 而事件还未发送之前被调用,可以用于做一些准备工作。
2). unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。
2. 创建被观察者Observable,它决定什么时候触发事件以及触发怎样的事件。实现代码如下:
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("tag1");
subscriber.onNext("tag2");
subscriber.onNext("tag3");
subscriber.onCompleted();
}
});
这里传入了一个 OnSubscribe 对象作为参数。OnSubscribe 会被存储在返回的 Observable 对象中,它的作用相当于一个计划表,当 Observable 被订阅的时候,OnSubscribe 的 call() 方法会自动被调用,事件序列就会依照设定依次触发(对于上面的代码,就是观察者Subscriber 将会被调用三次 onNext() 和一次 onCompleted())。这样,由被观察者调用了观察者的回调方法,就实现了由被观察者向观察者的事件传递,即观察者模式。
3. Subscribe订阅关系
创建了 Observable 和 Observer 之后,再用 subscribe() 方法将它们联结起来,整条链子就可以工作了
observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);
在RxJava 中,Scheduler ——调度器,相当于线程控制器,RxJava 通过它来指定每一段代码应该运行在什么样的线程。RxJava 已经内置了几个 Scheduler ,它们已经适合大多数的使用场景。
1. Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程这是默认的 Scheduler。
2. Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
3. Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
4. Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
有了这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。 * subscribeOn(): 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。 * observeOn(): 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。
Create->通过调用观察者的方法从头创建一个Observable。
Empty/Never/Throw ->创建行为受限的特殊Observable。
Defer->在观察者订阅之前不创建这个Observable,为每一个观察者创建一个新的Observable。
Just -> 将对象或者对象集合转换为一个会发射这些对象的Observable。
From -> 将其它的对象或数据结构转换为Observable。
Range ->创建发射指定范围的整数序列的Observable,range操作符,发射从start开始的count个数。
Interval->间隔一定时间发送一个数字,从0开始.本身运行在Schedulers.computation() 线程内。
Repeat ->Repeat作用在Observable上,会对其重复发射count次。
Timer ->会在指定时间后发射一个数字0,注意其也是运行在computation Scheduler
Buffer ->缓存,可以简单的理解为缓存,它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个。
FlatMap -> 扁平映射,将Observable发射的数据变换为Observables集合,然后将这些Observable发射的数据平坦化的放进一个单独的。Observable ->可以认为是一个将嵌套的数据结构展开的过程。
GroupBy -> 分组,将原来的Observable分拆为Observable集合,将原始Observable发射的数据按Key分组,每一个Observable发射一组不同的数据。
Map -> 映射,通过对序列的每一项都应用一个函数变换Observable发射的数据,实质是对序列中的每一项执行一个函数,函数的参数就是这个数据项。
Scan - > 扫描, 连续地对数据序列的每一项应用一个函数,然后连续发射结果,每一项结果基于之前的结果.累加器函数。
Window -> 窗口,定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项。类似于Buffer,但Buffer发射的是数据,Window发射的是Observable,每一个Observable发射原始Observable的数据的一个子集。
toList -> 将一个Observable转换为一个List。
Catch -> 捕获,继续序列操作,将错误替换为正常的数据,从onError通知中恢复。
onErrorReturn -> 当发生错误的时候,让Observable发射一个预先定义好的数据并正常地终止,不会抛出异常 onErrorResumeNext
当发生错误的时候,由另外一个Observable来代替当前的Observable并继续发射数据 onExceptionResumeNext
类似于OnErrorResume,不同之处在于其会对onError抛出的数据类型做判断,如果是Exception,也会使用另外一个Observable代替原Observable继续发射数据,否则会将错误分发给Subscriber。
Retry -> 重试,如果Observable发射了一个错误通知,重新订阅它,期待它正常终止。
retry -> Retry操作符在发生错误的时候会重新进行订阅,而且可以重复多次,所以发射的数据可能会产生重复。如果重复指定次数还有错误的话就会将错误返回给观察者,会掉onError retryWhen当错误发生时retryWhen会接收onError的throwable作为参数,并根据定义好的函数返回一个Observable,如果这个Observable发射一个数据,就会重新订阅。需要注意的是使用retryWhen的时候,因为每次重新订阅都会产生错误,所以作为参数的obserbvable会不断地发射数据,使用zipWith操作符可以限制重新订阅的次数,否则会无限制地重新订阅。会正常结束,调用onCompleted。
Delay -> 延迟一段时间发射结果数据 。
DelaySubscription -> 延迟注册到Observer上。
Do ->
doOnEach ->
doOnNext -> 只有onNext的时候才会被触发。
doOnSubscribeOn - > 在开始注册前做一些工作。处于当前线程,而不是subscribeOn指定的线程。
DoOnError -> 在OnError发生的时候触发回调,并将Throwable对象作为参数传进回调函数里。
DoOnComplete会在OnCompleted发生的时候触发回调。
DoOnTerminate ->
ObserveOn -> 指定Subscriber的调度程序(工作线程)。
SubscribeOn -> 指定Observable应该在哪个调度程序上执行。
Serialize ->
Subscribe ->
TimeInterval ->
Timeout ->
Timestamp ->
Using ->
And/Then/When - > 通过模式(And条件)和计划(Then次序)组合两个或多个Observable发射的数据集。
CombineLatest ->
Join->
Merge ->
StartWith ->
Zip -> Zip操作符将多个Observable发射的数据按顺序组合起来,每个数据只能组合一次,而且都是有序的。最终组合的数据的数量由发射数据最少的Observable来决定。
滤掉数据集合中我们不想要的数据。用于从Observable发射的数据中进行选择。
throttleWithTimeout ->
Debounce ->
Distinct -> 去重,过滤掉所有的重复数据项。
DistinctUtilChanged -> 过滤掉相邻的重复项。
ElementAt -> 取值,取特定位置的数据项。
Filter -> 过滤,过滤掉没有通过谓词测试的数据项,只发射通过测试的。
First ->
IgnoreElements -> 忽略所有的数据,只保留终止通知(onError或onCompleted)。
Sample -> 取样,定期发射最新的数据,等于是数据抽样。
ThrottleFirst -> 会定期发射这个时间段里源Observable发射的第一个数据。
Skip -> 跳过前面的若干项数据。
SkipLast -> 跳过后面的若干项数据。
Take -> 只保留前面的若干项数据。
TakeLast -> 只保留后面的若干项数据。
takeFirst -> 有null数据时会抛空指针异常,要判空处理
和first一样,但在所有数据不满足条件时不会抛出异常,仅仅调用onComplete。
这些操作符可用于单个或多个数据项,也可用于Observable
All
判断Observable发射的所有的数据项是否都满足某个条件
All操作符根据一个函数对源Observable发射的所有数据进行判断,最终返回的结果就是这个判断结果。
对发射的所有数据应用这个函数,如果全部都满足则返回true,否则就返回false。
Amb
Amb操作符可以将至多9个Observable结合起来,让他们竞争。
哪个Observable首先发射了数据(包括onError和onComplete)就会继续发射这个Observable的数据,其他的Observable所发射的数据都会别丢弃。
Contains
判断Observable是否会发射一个指定的数据项
Contains操作符用来判断源Observable所发射的数据是否包含某一个数据,如果包含会返回true,如果源Observable已经结束了却还没有发射这个数据则返回false。
IsEmpty
IsEmpty操作符用来判断源Observable是否发射过数据,没有发射过数据返回true.
Null也是一个数据
DefaultIfEmpty
发射来自原始Observable的数据,如果原始Observable没有发射数据,就发射一个默认数据
会判断源Observable是否发射数据,如果源Observable发射了数据则正常发射这些数据,如果没有则发射一个默认的数据
SequenceEqual
判断两个Observable是否按相同的数据序列
SequenceEqual操作符用来判断两个Observable发射的数据序列是否相同(发射的数据相同,数据的序列相同,结束的状态相同),如果相同返回true,否则返回false
SkipUntil
SkipUnitl是根据一个标志Observable来判断的,当这个标志Observable没有发射数据的时候,所有源Observable发射的数据都会被跳过;当标志Observable发射了一个数据,则开始正常地发射数据。
一直等到skipUntil发射了数据才能发射源Observable的数据,并忽略了此段时间内的数据
SkipWhile
SkipWhile则是根据一个函数来判断是否跳过数据,当函数返回值为true的时候则一直跳过源Observable发射的数据;当函数返回false的时候则开始正常发射数据。
TakeUntil
和SkipUtil恰好相反,只获取takeUntil里的Observable之前的数据
TakeWhile
和SkipWhile相反,获取满足skipWhile的数据
Concat
将多个Observable结合成一个Observable并发射数据,并且严格按照先后顺序发射数据,前一个Observable的数据没有发射完,不发射后面Observable的数据
Count
Count操作符用来统计源Observable发射了多少个数据,最后将数目给发射出来;
如果源Observable发射错误,则会将错误直接报出来;在源Observable没有终止前,count是不会发射统计数据的。
Reduce
Reduce操作符应用一个函数接收Observable发射的数据和函数的计算结果作为下次计算的参数,输出最后的结果。
跟前面我们了解过的scan操作符很类似,只是scan会输出每次计算的结果,而reduce只会输出最后的结果。
Collect
collect用来将源Observable发射的数据给收集到一个数据结构里面,需要使用两个参数:
一个产生收集数据结构的函数
一个接收第一个函数产生的数据结构和源Observable发射的数据作为参数的函数。
一些有精确可控的订阅行为的特殊Observable
什么是Connectable Observable:
就是一种特殊的Observable对象,并不是Subscrib的时候就发射数据,而是只有对其应用connect操作符的时候才开始发射数据,
所以可以用来更灵活的控制数据发射的时机。
使用Publish操作符将Observable转换为Connectable Observable,然后可以通过connect控制何时发射。
Publish -> 将一个的Observable转换为可连接的
Publish操作符就是用来将一个普通的Observable对象转化为一个Connectable Observable。需要注意的是如果发射数据已经开始了再进行订阅只能接收以后发射的数据。
Connect -> Connect操作符就是用来触发Connectable Observable发射数据的。
应用Connect操作符后会返回一个Subscription对象,通过这个Subscription对象,我们可以调用其unsubscribe方法来终止数据的发射。
RefCount -> RefCount操作符就是将一个Connectable Observable 对象再重新转化为一个普通的Observable对象,这时候订阅者进行订阅时就会触发数据的发射。
Replay -> Replay操作符返回一个Connectable Observable 对象并且可以缓存其发射过的数据,这样即使有订阅者在其发射数据之后进行订阅也能收到其之前发射过的数据。
参考文章:
给 Android 开发者的 RxJava 详解
Android RxJava操作符一览