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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值