RxJava简介
概念
“RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences.”
—— RxJava Repo
RxJava是Java VM上一个灵活的、使用可观测序列来组成的一个异步的、基于事件的库。
作用 - 异步
核心的东西不外乎两个, Observables(被观察者) 和 Subscribers(观察者)。Observables可以发出一系列的 事件,这里的事件可以是任何东西,例如网络请求、复杂计算、数据库操作、文件读取等等,事件执行结束后交给Subscribers的回调处理。
设计模式 - 观察者模式
观察者模式是对象的行为模式,也叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。 例如用过EventBus同学就知道,EventBus属于Publish/Subscribe模式。
什么是观察者模式?举个例子,Android中View的点击监听器的实现,View是被观察者,OnClickListener对象是观察者,Activity要如何知道View被点击了?那就是派一个OnClickListener对象,入驻View,与View达成一个订阅关系,一旦View被点击了,就通过OnClickListener对象的OnClick方法传达给Activity。采用观察者模式可以避免去轮询检查,节约有限的cpu资源。
结构 - 响应式编程
什么是响应式编程?举个例子,a = b + c; 这句代码将b+c的值赋给a,而之后如果b和c的值改变了不会影响到a,然而,对于响应式编程,之后b和c的值的改变也动态影响着a,意味着a会随着b和c的变化而变化。
优势 - 逻辑简洁
逻辑简洁并不意味着代码简洁,但是,由于链式结构,一条龙,你可以从头到尾,从上到下,很清楚的看到这个连式结构的执行顺序。对于开发人员来说,代码质量并不在于代码量,而在于逻辑清晰简洁,可维护性好,代码健壮!
初始化源码分析
观察者 Observer
只是一个接口,具体实现由用户决定
public interface Observer<@NonNull T> {
void onSubscribe(@NonNull Disposable d); // 订阅后回调
void onNext(@NonNull T t); // 接受下一个事件时回调
void onError(@NonNull Throwable e); // 出现错误时回调(比如抛异常)
void onComplete(); // 事件流完成后回调
}
被观察者 Observable
会返回一个 ObservableCreate<T>,就是自定义Source
订阅过程分析
主流程分析
使用一个简单的示例:create后直接subscribe
示例代码
// 起点
Observable.create(
object : ObservableOnSubscribe<String> {
override fun subscribe(emitter: ObservableEmitter<String>) {
// emitter 就是自定义 Source
// 最终让 ObservableCreate.source: ObservableOnSubscribe<T> 保存 【埋下伏笔】
emitter.onNext("RxJava") // 开始拆洋葱模型【一级包裹】
}
}
)
.subscribe(
// 终点
object : Observer<String> {
override fun onSubscribe(d: Disposable) {
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
}
override fun onNext(t: Boolean) {
Log.d(TAG, "this is onNext()")
}
}
)
流程分析
在起点Obserable和终点Observer,都是面向接口编程(依赖倒置原则)。框架只实现思路(接口),具体代码(实现)由用户完成。
e.onNext()就是拆包裹的开始,这就是为什么想要启动整个事件流必须要在Observable中写e.onNext()的原因。
source是ObservableSource<T>类型,ObservableSource<T>实际上是个接口,内部只有一个subscribe,传递了终点Observer。
map变换流程分析
使用一个简单的示例:create后连接一次map,之后直接subscribe
示例代码
// 起点
Observable.create(
object : ObservableOnSubscribe<String> {
override fun subscribe(emitter: ObservableEmitter<String>) {
// emitter 就是自定义 Source
// 最终让 ObservableCreate.source: ObservableOnSubscribe<T> 保存了 【埋下伏笔】
emitter.onNext("RxJava") // 开始拆洋葱模型【一级包裹】
}
}
)
// 需求一
/**
* map 变换
*/
.map {
// 框架不管细节,将细节交给用户(面向接口编程 / 依赖倒置原则)
return@map 1
}
.subscribe(
// 终点
object : Observer<Boolean> {
override fun onSubscribe(d: Disposable) {
Log.d(TAG, "this is onSubscribe()")
}
override fun onError(e: Throwable) {
Log.d(TAG, "this is onError()")
}
override fun onComplete() {
Log.d(TAG, "this is onComplete()")
}
override fun onNext(t: Boolean) {
Log.d(TAG, "this is onNext()")
}
}
)
流程分析
总体上,加入map操作符的流程和不加map操作符的流程大同小异,但是需要特别关注的是ObserverMap中的onNext方法。
我们来看下源码:
// ObserverMap.java
final Function<? super T, ? extends U> mapper
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
downstream.onNext(null);
return;
}
U v;
try {
v = Objects.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
downstream.onNext(v);
}
// Function.java
public interface Function<@NonNull T, @NonNull R> {
R apply(T t) throws Throwable;
}
这里面的mapper实际上就是我们map操作符传进来的一个函数。而mapper.apply(t),本质是个接口,主要定义将T类型转为R类型,具体实现交给用户,又是面向接口编程。
结构
洋葱模型
就是RxJava对Observable<T>的一层层封装(这里借用一下网图,犯懒了)
U型结构
U型结构就是我们上面分析的两张订阅流程图中,红色箭头的流程
M型结构
主要包含三次数据的封装和拆解:
-
第一次,从Observable到Observer,将被观察者一层层包裹
-
第二次,从subscribe开始到ObservableOnSubscribe,根据包裹的被观察者创建出包裹的观察者
-
第三次,Observable的源头启动onNext()开始拆包裹,各个Observer观察到相应的Observable,并完成用户的操作,一直到最终的Observer被调用,完成用户实现的接口逻辑
线程切换
线程调度器
Schedulers.computation() | 用于计算任务,如事件循环或和回调处理,不要用于IO操作(IO操作请使用Schedulers.io());默认线程数等于处理器的数量 |
Schedulers.from(executor) | 使用指定的Executor作为调度器 |
Schedulers.immediate( ) | 在当前线程立即开始执行任务 |
Schedulers.io( ) | 用于IO密集型任务,如数据库读写,网络请求等 |
Schedulers.newThread( ) | 为每个任务创建一个新线程 |
Schedulers.trampoline( ) | 当其它排队的任务完成后,在当前线程排队开始执行 |
AndroidSchedulers.mainThread() | 用于Android的UI更新操作,任务执行在主线程中,一帮设置为observeOn的调度器,用于下游接收到数据流后更新UI |
subscribeOn()线程调度
在scheduleDirect中会从线程池中拿线程,而SubscribeTask就是一个Runnable,会执行source.subscribe(),这就联系到上面的流程图了。
// ObservableSubscribeOn.java
@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
DisposeTask task = new DisposeTask(decoratedRun, w);
w.schedule(task, delay, unit);
return task;
}
// IoSchedular.java
@NonNull
@Override
public Worker createWorker() {
return new EventLoopWorker(pool.get());
}
observerOn()线程调度
ObserveOnObserver有两点比较关键:
-
schedule()方法,最终调用到Observer.onNext(),可结合到上面的流程图
-
onNext()方法,最终调用ScheduleRunnable.setFuture(),使用线程池完成线程切换
// NewThreadWorker.java
@NonNull
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future<?> f;
try {
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
public void setFuture(Future<?> f) {
for (;;) {
Object o = get(FUTURE_INDEX);
if (o == DONE) {
return;
}
if (o == SYNC_DISPOSED) {
f.cancel(false);
return;
}
if (o == ASYNC_DISPOSED) {
f.cancel(true);
return;
}
if (compareAndSet(FUTURE_INDEX, o, f)) {
return;
}
}
}