RxJava线程切换非常方便,只要调用subscribeOn(Schedules.io())就可以使前边的操作运行于子线程,调用obsersableOn(AndroidSchedules.mainThread())就可以设置后边的代码运行于主线程,那么是如此神奇,他是如何实现的?
今天就以下边的代码为切入点深入源码看一下
Observable.just("我是网络图片url").map(new Function() {
@Override
public String apply(@NonNull String s) throws Exception {
Log.i(TAG, "apply1 thread:"+Thread.currentThread().getName());
Log.i(TAG, "apply1");
s = s +" 加上一个时间戳后";
return s;
}
}).map(new Function() {
@Override
public String apply(@NonNull String s) throws Exception {
Log.i(TAG, "apply2 thread:"+Thread.currentThread().getName());
Log.i(TAG, "apply2");
s = s +" 加上第二个参数后";
return s;
}
}).subscribeOn(Schedulers.io()).subscribe(new Observer() {
@Override
public void onSubscribe() {
Log.i(TAG, "onSubscribe thread:"+Thread.currentThread().getName());
Log.i(TAG, "onSubscribe");
}
@Override
public void onNext(@NonNull String s) {
Log.i(TAG, "onNext thread:"+Thread.currentThread().getName());
Log.i(TAG, "onNext:"+s+" 开启下载这个图片");
}
@Override
public void onError(@NonNull Throwable throwable) {
Log.i(TAG, "onError");
throwable.printStackTrace();
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete thread:"+Thread.currentThread().getName());
Log.i(TAG, "onComplete:下载完成");
}
});
程序运行流程图如下
just方法
创建一个ObservableJust对象返回,并将just传入的参数保保存为value
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static Observable just(T item) {
ObjectHelper.requireNonNull(item, "The item is null");
return RxJavaPlugins.onAssembly(new ObservableJust(item));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@NonNull
public static Observable onAssembly(@NonNull Observable source) {
Function super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
}
map方法
同样道理,创建一个ObservableMap对象,由于map方法由上边的ObservableJust对象调用,所以构造方法中传入的this表示的就是ObservableJust对象,创建ObservableMap对象后,保存上一级产生的ObservableJust为当前ObservableMap对象中的成员变量source,保存当前function回调接口,这样一来,当前对象持有上一级ObservableJust的引用。不管map调用几次,当前对象都会持有上一级产生的对象的引用
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable map(Function super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap(this, mapper));
}
假设再次调用map之后,这个map就是由上一次调用map产生的ObservableMap对象调用的,此时会将上一级这个ObservableMap对象保存到当前对象的source成员变量中,就这样,一级套一级
subscribeOn方法
产生一个ObservableSubscribeOn对象,并将上一级的ObservableMap对象保存为当前对象的source变量,保存传入的scheduler,那么这个scheduler是什么?
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn(this, scheduler));
}
subscribeOn(Schedulers.io())方法使上边的操作在子线程中执行,Schedulers.io()就是上边传入的schedulers,我们看一下schedulers是如何创建的
来到Schedulers类中
public static Scheduler io() {
return RxJavaPlugins.onIoScheduler(IO);
}
可以找到IO对象是在本类静态代码块中创建的
static {
....
IO = RxJavaPlugins.initIoScheduler(new IOTask());
....
}
IOTask是一个实现了Callable接口的线程
static final class IOTask implements Callable {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
}
}
线程执行会得到Scheduler,可以看到,这是以内部类形式实现的单例模式
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
可以看到,这个IoScheduler内部是线程池实现的
CachedWorkerPool update = new CachedWorkerPool(KEEP_ALIVE_TIME, KEEP_ALIVE_UNIT, threadFactory);
也就是说,当我们在代码中设置了这个操作之后(subscribeOn(Schedulers.io())),会创建一个线程池(如果存在就不必创建),很明显,最终将会需要放在子线程中执行的方法在这个线程池中执行,从而达到切换线程的效果,目前看到这里,这只能作为一个猜想,我们继续往下看
observeOn(AndroidSchedulers.mainThread())方法
这个方法执行会保存一个运行于主线程的Scheduler,这个主线程Scheduler如何创建的?
AndroidSchedulers中
private static final class MainHolder {
static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));
}
private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
new Callable() {
@Override public Scheduler call() throws Exception {
return MainHolder.DEFAULT;
}
});
/** A {@link Scheduler} which executes actions on the Android main thread. */
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
可以看到这个Scheduler是通过封装Handler得到的一个运行于主线程的封装类,这里将它保存起来。最后我们看subscribe方法
subscribe方法
public final void subscribe(Observer super T> observer) {
......
subscribeActual(observer);
......
}
protected abstract void subscribeActual(Observer super T> observer);
由于subscribeActual方法是抽象的,那么要从其子类中找,subscribe方法由上次操作observeOn方法得到的ObservableObserveOn对象调用,所以会执行这个类中的subscribeActual方法,进入ObservableObserveOn中
@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(observer, w, delayError, bufferSize));
}
}
scheduler就是之前保存的AndroidSchedulers.mainThread对象,这里的source表示的就是上一级产生的Observable对象,具体到当前代码,就是ObservableSubscribeOn,调用ObservableSubscribeOn中的subscribe方法,逐层向上传递,直到传递到ObservableJust对象中,再不断的调用map中传入的function回调方法apply,当apply方法调用完成,再执行Observer的onNext onComplete方法,具体流程见上边的流程图,下一篇博客我将会详细分析线程调度的源码。
到这里,这段示例代码的流程已经走了一遍
写了一个简化版的RxJava,实现了just map subscribeOn obserseOn方法,有助于对原理的理解,GitHub地址:https://github.com/renzhenming/MyRxJava