【RxJava】从自定义Schedulers.computation到RxJava的Hook

使用自定义Schedulers.computation

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

hookRxJavaPlugins返回的,如果没有单独处理,返回的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,并在RxJavaSchedulersHookgetComputationScheduler返回自定义的ComputationScheduler即可。

RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook(){
    @Override
    public Scheduler getComputationScheduler() {
        return 自定义的Scheduler;
    }
});

RxJavaSchedulersHook

提然提到了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包

除了自定义线程池外,plugins包含了hook相关的内容

【RxJava】从自定义Schedulers.computation到RxJava的Hook_第1张图片

RxJavaHooks

使用RxJavaHooks可以hook到Observable、Single和Completable类型、Schedulers返回的Scheduler的生命周期,并且可以错误提供了一个全面的解决方案。

【RxJava】从自定义Schedulers.computation到RxJava的Hook_第2张图片

RxJavaHooks定义了很多静态属性:

【RxJava】从自定义Schedulers.computation到RxJava的Hook_第3张图片

每一个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

你可能感兴趣的:(rxjava,rxjava,java,android)