中文文档 mcxiaoke.gitbooks.io/rxdocs/
Github地址 github.com/ReactiveX/R…
一. RxJava的作用、能解决的问题:
- 线程切换
- 数据流处理,map、transform等
一句话总结:使用可观察数据流进行异步编程
二. 基础概念
1. Observable:被观察者
它是一个抽象类,实现接口ObservableSource,使观察者可订阅到该可观察源实例。
它支持一系列转换,所以有很多对应的方法,这是所有被观察者共有的。
为了使用方便,根据发射数据的方式,它细分出了一些常用的Observable,它们都继承自抽象类Observable,内部使用自己的发射器Emitter发射数据。
public interface ObservableSource<T> {
//唯一的方法,将指定的观察者订阅到该可观察源实例
//观察者不能为空,否则会有NPE
void subscribe(@NonNull Observer<? super T> observer);
}
public interface Emitter {
//发射一个非空的值
onNext(@NonNull T value)
//发射一个非空的异常
onError(@NonNull Throwable error)
//一个完成的信号
onComplete()
}
2. AbstractObservableWithUpstream
除初始Observable以外,中间的Observable流都继承自它,确保持有上游Observable的引用。(这里需要了解Rxjava将所有对Observable的操作都封装成了一个这个类的子类)
3. Observer
观察者,对事件源的操作进行响应及处理。
public interface Observer<T> {
//接收可中断的订阅流
void onSubscribe(@NonNull Disposable d);
void onNext(@NonNull T t);
void onError(@NonNull Throwable e);
void onComplete();
}
⚠️注意:onError 和 onComplete 只会执行其中一个,因为 Emitter 中 onError 和 onComplete 的时候最终都会执行dispose(),onError 和 onComplete 内容执行的条件是!isDisposed()。
4. Single
它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。
Single类似于Observable,不同的是,它总是只发射一个值,或者一个错误通知,而不是发射一系列的值。
因此,不同于Observable需要三个方法onNext, onError, onCompleted,订阅Single只需要两个方法:
- onSuccess - Single发射单个的值到这个方法
- onError - 如果无法发射需要的值,Single发射一个Throwable对象到这个方法
Single只会调用这两个方法中的一个,而且只会调用一次,调用了任何一个方法之后,订阅关系终止。
5. Subject
它同时充当了Observer和Observable的角色。
Subject可以看成是一个桥梁或者代理,它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。
分类如下:(类型特质 : mcxiaoke.gitbooks.io/rxdocs/Subj…)
- AsyncSubject
- BehaviorSubject
- PublishSubject
- ReplaySubject
三. 调度器
| 调度器类型 | 效果 |
|---|---|
| Schedulers.computation( ) | 用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量 |
| Schedulers.from(executor) | 使用指定的Executor作为调度器 |
| Schedulers.immediate( ) | 在当前线程立即开始执行任务 |
| Schedulers.io( ) | 用于IO密集型任务,如异步阻塞IO操作,这个调度器的线程池会根据需要增长;对于普通的计算任务,请使用Schedulers.computation();Schedulers.io( )默认是一个CachedThreadScheduler,很像一个有线程缓存的新线程调度器 |
| Schedulers.newThread( ) | 为每个任务创建一个新线程 |
| Schedulers.trampoline( ) | 当其它排队的任务完成后,在当前线程排队开始执行 |
四. Observable线程控制
Observable.subscribeOn(Scheduler) 指定初始被观察者的执行线程,它返回一个重新封装好的Observable oso,叫ObservableSubscribeOn。因为oso继承自Observable,所以它的执行操作也在核心方法subscribeActual中,即线程调度的操作在subscribeActual中执行。它要处理初始被观察者的执行线程,那么它一定持有初始被观察者的引用和线程调度器Scheduler的引用。ObservableSubscribeOn中subscribeActual方法如下:
@Overridepublic void subscribeActual(final Observer<? super T> observer) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);
observer.onSubscribe(parent);
//注意:scheduler.scheduleDirect 进行线程控制
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
//source为初始被观察者
source.subscribe(parent);
}
}
问题1: 如果subscribeOn(Scheduler)设置多次,那究竟哪次的有效?
答案:这是一个递归的过程,observable流会先执行它的上游内容,所以最先执行初始Observable的subscribeActual。如果有设置subscribeOn(Scheduler),那么初始Observable会变成裹几层糖衣的ObservableSubscribeOn。不管糖衣有几层,最后对初始Observable进行线程控制的肯定是最里层的糖衣,即第一个设置的Scheduler。
Observable.observeOn(Scheduler) 指定观察者/下游Observable(特殊的Observer)的执行线程,它返回新的Observable ooo,叫ObservableObserveOn。Observable原本的内容不变,只是把Observer重新封装,叫ObserveOnObserver。它要处理观察者的执行线程,那么它一定持有观察者的引用和工作线程相关的引用。ObserveOnObserver实现了Observer、Runnable接口。ObservableObserveOn中subscribeActual方法如下:
@Override
protected void subscribeActual(Observer<? super T> observer) {
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
Scheduler.Worker w = scheduler.createWorker();
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
//-----------以下是ObserveOnObserver部分代码-------------
//ObserveOnObserver中,onNext、onError、onComplete方法都会调用该方法,实现线程调度
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
@Overridepublic void run() {
if (outputFused) { drainFused(); }
else { drainNormal(); }
}
嗯,顺便注意下 thread.run() 和 thread.start()
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
getVal();
}
}, "Thread-1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
thread1.start(); //Thread-1
//thread1.run(); //Thread-2 }
}, "Thread-2");private static void getVal() {
System.out.println(Thread.currentThread().getName());
}
总结:就近原则,subscribeOn看第一次设置的值,离原始observable最近的那行;observeOn看离observer最近的那行,observer那行代码上方最后设置的那行。
subscribeOn相当于给Observable外面裹糖衣,它内部实现全都保持不变,糖衣层进行线程调度;最终控制observable线程的是最内层的糖衣,即第一次设置的值;
observeOn相当于给Observer外面裹糖衣,它内部实现全都保持不变,糖衣层进行线程调度;最终控制observer线程的是包裹它的最内层的糖衣,即第一次设置的值,因为observable.subscribe(observer)是从下游observable递归调用到上游observable,生效的是subscribe(observer)后第一次设置的observeOn(scheduler)的值,所以真正的控制线程是subscribe(observer)对应代码行上方离它最近的observeOn那行设置的值。
五. 数据转换等处理
数据转换以map操作为例:它生成一个新的Observable,叫ObservableMap。map的作用是对上游Observable发射的数据进行处理再发送给下游Observable,所以对上游Observable而言,它就是一个Observer。
@Override
public void subscribeActual(Observer<? super U> t) {
//把map的功能附加到原本的observer上
source.subscribe(new MapObserver<T, U>(t, function));
}
//-----------以下是MapObserver部分代码-------------@Override
public void onNext(T t) {
if (done) { return; }
if (sourceMode != NONE) { downstream.onNext(null); return; }
U v;
try {
//此处执行map的功能
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
//将转换后的数据发送给下游接收者
downstream.onNext(v);
}
-
Map-> transform the items emitted by an Observable by applying a function to each item -
FlatMap-> transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single ObservableV.S.
Map只是对一个Observable发送的所有数据进行一个fuction变换;
FlatMap是将一个Observable变换到多个Observable然后再flat到一个Observable发送;
-
Zip-> combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function -
Concat-> emit the emissions from two or more Observables without interleaving them -
Merge-> combine multiple Observables into one by merging their emissions
V.S.
zip并不会影响多个Observable的发送时间然后依据设置的方式将返回结果组合;
Contact会依照组合的顺序依次发送Observable(第一个没有执行完,不会执行第二个Observable);
Merge会讲多个Observable合并成一个(与zip的区别因该是不会进行再变形操作)
Take-> emit only the first n items emitted by an ObservableReduce-> apply a function to each item emitted by an Observable, sequentially, and emit the final valueSkip-> suppress the first n items emitted by an ObservableBuffer-> periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a timeReplay-> ensure that all observers see the same sequence of emitted items, even if they subscribe after the Observable has begun emitting itemsFilter-> emit only those items from an Observable that pass a predicate test