[RxJava] Hook from custom Schedulers.computation to RxJava

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);
}

RxJavaHooksCreate 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 hookit 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();
    }
}

hookIt is returned. If it is not processed separately, the default instance is RxJavaPluginsreturned , which is returned in this instance .hookRxJavaSchedulersHookgetComputationSchedulernull

At the same time, a method RxJavaPluginsis 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 RxJavaPluginsregister one in RxJavaSchedulersHookand return the custom one RxJavaSchedulersHookin .getComputationSchedulerComputationScheduler

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

insert image description here

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.

insert image description here

RxJavaHooks defines many static properties:

insert image description here

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

Guess you like

Origin blog.csdn.net/qq_23049111/article/details/127296130