Scheduler是Rxjava关于线程的抽象类。
Schedulers封装了一些常用的线程。
例如io线程io()
,计算线程computation()
等等。
以computation()
为例,看一下Schedulers是怎么样工作的:
#Schedulers
public static Scheduler computation() {
return RxJavaHooks.onComputationScheduler(getInstance().computationScheduler);
}
RxJavaHooks
没有处理ComputationScheduler
的创建工作,按下不表:
#RxJavaHooks
static volatile Func1<Scheduler, Scheduler> onComputationScheduler;
public static Scheduler onComputationScheduler(Scheduler scheduler) {
Func1<Scheduler, Scheduler> f = onComputationScheduler;
if (f != null) {
return f.call(scheduler);
}
return scheduler;
}
public static void setOnComputationScheduler(Func1<Scheduler, Scheduler> onComputationScheduler) {
if (lockdown) {
return;
}
RxJavaHooks.onComputationScheduler = onComputationScheduler;
}
Schedulers的构造方法内,获取了RxJavaSchedulersHook实例hook
,如果hook
返回了ComputationScheduler
,则使用这个ComputationScheduler
。
#Schedulers
private final Scheduler computationScheduler;
private Schedulers() {
RxJavaSchedulersHook hook = RxJavaPlugins.getInstance().getSchedulersHook();
Scheduler c = hook.getComputationScheduler();
if (c != null) {
computationScheduler = c;
} else {
computationScheduler = RxJavaSchedulersHook.createComputationScheduler();
}
}
hook
是RxJavaPlugins
返回的,如果没有单独处理,返回的hook
是默认的RxJavaSchedulersHook
实例,这个实例中getComputationScheduler
返回的是null
。
同时,RxJavaPlugins
提供了registerSchedulersHook
方法,我们可以调用这个方法,设置自定义的RxJavaSchedulersHook
。
#RxJavaPlugins
public RxJavaSchedulersHook getSchedulersHook() {
if (schedulersHook.get() == null) {
Object impl = getPluginImplementationViaProperty(RxJavaSchedulersHook.class, System.getProperties());
if (impl == null) {
schedulersHook.compareAndSet(null, RxJavaSchedulersHook.getDefaultInstance());
} else {
schedulersHook.compareAndSet(null, (RxJavaSchedulersHook) impl);
}
}
return schedulersHook.get();
}
public void registerSchedulersHook(RxJavaSchedulersHook impl) {
if (!schedulersHook.compareAndSet(null, impl)) {
throw new IllegalStateException("Another strategy was already registered: " + schedulersHook.get());
}
}
#RxJavaSchedulersHook
public Scheduler getComputationScheduler() {
return null;
}
因此,想要使用自定义的ComputationScheduler
,只需要在RxJavaPlugins
注册一个RxJavaSchedulersHook
,并在RxJavaSchedulersHook
的getComputationScheduler
返回自定义的ComputationScheduler
即可。
RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook(){
@Override
public Scheduler getComputationScheduler() {
return 自定义的Scheduler;
}
});
提然提到了RxJavaSchedulersHook,不如继续了解下这个类。官方文档翻译如下:
提供了两种自定义Scheduler功能的方法
1.重新定义整个schedulers。复写io()、computation()、newThread()3个方法。
2.使用Action0进行包装/修饰。ioScheduler、computationScheduleer、newThreadScheduler都使用这个钩子,因此它非常便于修改scheduler功能。
#RxJavaSchedulersHook
public Scheduler getComputationScheduler() {
return null;
}
public Scheduler getIOScheduler() {
return null;
}
public Scheduler getNewThreadScheduler() {
return null;
}
#RxJavaSchedulersHook
public Action0 onSchedule(Action0 action) {
return action;
}
除了自定义线程池外,plugins包含了hook相关的内容
使用RxJavaHooks可以hook到Observable、Single和Completable类型、Schedulers返回的Scheduler的生命周期,并且可以错误提供了一个全面的解决方案。
RxJavaHooks定义了很多静态属性:
每一个on方法调用了对应的静态属性:
public static <T> Observable.OnSubscribe<T> onCreate(Observable.OnSubscribe<T> onSubscribe) {
Func1<Observable.OnSubscribe, Observable.OnSubscribe> f = onObservableCreate;
if (f != null) {
return f.call(onSubscribe);
}
return onSubscribe;
}
这些静态属性的初始化是在静态方法init中完成的:
static void init() {
onError = new Action1<Throwable>() {
@Override
public void call(Throwable e) {
RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
}
};
onObservableStart = new Func2<Observable, Observable.OnSubscribe, Observable.OnSubscribe>() {
@Override
public Observable.OnSubscribe call(Observable t1, Observable.OnSubscribe t2) {
return RxJavaPlugins.getInstance().getObservableExecutionHook().onSubscribeStart(t1, t2);
}
};
...
}
我们发现,实际的初始化是RxJavaPlugins完成的,RxJavaPlugins内定义了这几个属性:
public class RxJavaPlugins {
private final AtomicReference<RxJavaErrorHandler> errorHandler = new AtomicReference<RxJavaErrorHandler>();
private final AtomicReference<RxJavaObservableExecutionHook> observableExecutionHook = new AtomicReference<RxJavaObservableExecutionHook>();
private final AtomicReference<RxJavaSingleExecutionHook> singleExecutionHook = new AtomicReference<RxJavaSingleExecutionHook>();
private final AtomicReference<RxJavaCompletableExecutionHook> completableExecutionHook = new AtomicReference<RxJavaCompletableExecutionHook>();
private final AtomicReference<RxJavaSchedulersHook> schedulersHook = new AtomicReference<RxJavaSchedulersHook>();
}
并且提供了各自的get和set方法,这里的set用register代替了:
#省略类似方法
public RxJavaCompletableExecutionHook getCompletableExecutionHook() {
if (completableExecutionHook.get() == null) {
// check for an implementation from System.getProperty first
Object impl = getPluginImplementationViaProperty(RxJavaCompletableExecutionHook.class, System.getProperties());
...
return completableExecutionHook.get();
}
public void registerCompletableExecutionHook(RxJavaCompletableExecutionHook impl) {
if (!completableExecutionHook.compareAndSet(null, impl)) {
throw new IllegalStateException("Another strategy was already registered: " + singleExecutionHook.get());
}
}
因此,打算使用RxJavaHooks,必须通过RxJavaPlugins设置。
参考:
ReactiveX/RxJava/Plugins