Using custom Schedulers.computation
Scheduler is Rxjava's abstract class about threads.
Schedulers encapsulate some commonly used threads.
Such as io thread io()
, calculation thread computation()
and so on.
As computation()
an example, take a look at how Schedulers work:
#Schedulers
public static Scheduler computation() {
return RxJavaHooks.onComputationScheduler(getInstance().computationScheduler);
}
RxJavaHooks
Create jobs that are not processed ComputationScheduler
, press No:
#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;
}
In the construction method of Schedulers, the RxJavaSchedulersHook instance is obtained hook
, and if hook
it is returned ComputationScheduler
, use this 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
It is returned. If it is not processed separately, the default instance is RxJavaPlugins
returned , which is returned in this instance .hook
RxJavaSchedulersHook
getComputationScheduler
null
At the same time, a method RxJavaPlugins
is provided registerSchedulersHook
, we can call this method to set a custom one 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;
}
Therefore, if you want to use a custom one ComputationScheduler
, you only need to RxJavaPlugins
register one in RxJavaSchedulersHook
and return the custom one RxJavaSchedulersHook
in .getComputationScheduler
ComputationScheduler
RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook(){
@Override
public Scheduler getComputationScheduler() {
return 自定义的Scheduler;
}
});
RxJavaSchedulersHook
Although I mentioned RxJavaSchedulersHook, it is better to continue to understand this class. The official document translation is as follows:
Provides two ways to customize Scheduler functions
1. Redefine the entire schedulers. Override the 3 methods of io(), computation(), and newThread().
2. Use Action0 for wrapping/decorating. ioScheduler, computationScheduleer, newThreadScheduler all use this hook, so it is very convenient to modify the scheduler function.
#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 package
In addition to the custom thread pool, plugins contains hook-related content
RxJavaHooks
Using RxJavaHooks can hook to Observable, Single and Completable types, the life cycle of the Scheduler returned by Schedulers, and can provide a comprehensive solution for errors.
RxJavaHooks defines many static properties:
Each on method calls the corresponding static property:
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;
}
The initialization of these static properties is done in the static method 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);
}
};
...
}
We found that the actual initialization is done by RxJavaPlugins, and these properties are defined in 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>();
}
And provide their own get and set methods, where the set is replaced by 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());
}
}
Therefore, if you plan to use RxJavaHooks, you must set it through RxJavaPlugins.
Reference:
ReactiveX/RxJava/Plugins