Retrofit之RxJava流处理与线程控制
使用Retrofit发起一次RxJava式的网络请求的式例代码如下:
HttpManager.newRetrofit().create(FeedbackApi::class.java)
.report()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(object : StringHttpResult() {})
1. JxJava流处理过程
这里report()方法返回的是一个Observable对象,是所有流的源头,observeOn()方法和subscribeOn()方法分别对源头进行封装,源头先被封装成一个ObservableObserveOn对象,然后又将ObservableObserveOn对象封装成一个ObservableObserveOn对象,如下图左边部分所示:
最后再调用最底层ObservableObserveOn对象的subscribe()方法,会层层递归调用到源头CallExecuteObservable的subscribe()方法,使得每一层的Observable都得到一个订阅者,从上到下分别是ObserveOnObserver、SubscribeOnObserver和自定义Observer,如上图右半部分所示。
1.1. 订阅过程
首先是用户调用ObservableSubscribeOn的subscribe()方法触发subscribeActual()方法调用:
//ObservableSubscribeOn.java
@Override
public void subscribeActual(final Observer<? super T> observer) {
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);
observer.onSubscribe(parent);
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
这里自定义的Observer对象被包装成一个SubscribeOnObserver()对象,然后将该对象订阅给ObservableSubscribeOn的suorce对象,由上图知道该source对象实际是ObservableObserveOn对象,因此又会触发ObservableObserveOn对象的subscribeActual()方法调用:
//ObservableObserveOn.java
@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));
}
}
这里的source是CallExecuteObservable对象,因此会调用:
@Override
protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallDisposable disposable = new CallDisposable(call);
//onSubscribe回调
observer.onSubscribe(disposable);
if (disposable.isDisposed()) {
return;
}
boolean terminated = false;
try {
Response<T> response = call.execute();
if (!disposable.isDisposed()) {
//onNext回调
observer.onNext(response);
}
if (!disposable.isDisposed()) {
terminated = true;
//onComplete回调
observer.onComplete();
}
}
//onError回调
}
这里可以看到Okhttp最终使用Call对象的execute()方法发起同步请求的,因此在Retrofit发起网络请求是要注意线程切换。到execute()返回时,将返回的response对象交给observer的onNext()处理,即是将源头产生的流交给下游的观察者处理。
1.2 流处理过程
假设全过程无错,因此会回调onNext()方法,先是回调ObserveOnObserver对象的onNext()方法:
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
worker.schedule(this);
}
}
将上游产生的对象放入queue队列中,这里的worker即AndroidSchedulers.mainThread()的到的主线程Scheduler对象,ObserveOnObserver实现了Runnable接口,因此重写的run()方法会在主线程执行。看一下从队列中去取元素的过程:
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
final Observer<? super T> a = downstream;
for (;;) {//相当于自旋所
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
for (;;) {//取出队列中的所有元素
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
disposed = true;
upstream.dispose();
q.clear();
a.onError(ex);
worker.dispose();
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
a.onNext(v);
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
这段代码主要就是两个循环,第一个循环是为操作公共资源加自旋转锁,第二个循环是取出队列中的所有元素并交给下游处理。还有一个drainFused()版本的函数,该函数是仅当处于ASYNC模式时执行,源码中注释说明处于异步融合模式中,上游的onError()和onComplete()和同步模式一样,但是onNext()却不包含上流的信号而是返回null给下游。
2. 线程控制
调度器控制线程,所有调度器的父类是Scheduler,其实现类有很多,下面看一下IoScheduler的实现:
Scheduler类提供了一个虚方法create()来创建一个Scheduler.Worker对象,IoScheduler类的实现是创建一个EventLoopWorker对象,因此该对象是调度的入口点。Scheduler中有一个工作者缓存池对象,其缓存一系列ThreadWorker对象,每个ThreadWorker对象中又各自包含一个executor线程池,看一下NewThreadWorker线程池的初始化:
//NewThreadWorker.java
public NewThreadWorker(ThreadFactory threadFactory) {
executor = SchedulerPoolFactory.create(threadFactory);
}
//SchedulerPoolFactory.java
public static ScheduledExecutorService create(ThreadFactory factory) {
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
tryPutIntoPool(PURGE_ENABLED, exec);
return exec;
}
tryPutIntoPool()方法会将exec缓存,并开启一个定时任务来清理该缓存池中已经关闭的ScheduledExecutorService。IO调度中,工作者缓存池缓存了ThreadWorker对象,每个ThreadWorker对象又对应一个ScheduledExecutorService。