RxJava(被)观察者创建与线程调度

本文使用rxjava2版本进行讲解:

implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'io.reactivex.rxjava2:rxjava:2.1.8'

0、 代码实例

//被观察者
Observable observable= Observable.create(new ObservableOnSubscribe<String>() {

    @Override
    public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
        Log.d(TAG, "subscribe: ");
        emitter.onNext("hello");
        emitter.onNext("world");
        //emitter.onError(new Throwable("aa"));
        emitter.onComplete();

    }
});
//观察者
Observer<String> observer = new Observer<String>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {
        Log.d(TAG, "onSubscribe: ");
    }

    @Override
    public void onNext(@NonNull String s) {
        Log.d(TAG, "onNext: s="+s);
    }


    @Override
    public void onError(@NonNull Throwable e) {
        Log.d(TAG, "onError: "+e.getMessage());
    }

    @Override
    public void onComplete() {
        Log.d(TAG, "onComplete: ");
    }
};
observable
        .subscribeOn(Schedulers.io()) //被观察者事件切到io线程执行
       // .observeOn(AndroidSchedulers.mainThread()) //观察者事件切到android主线程执行
        .observeOn(Schedulers.newThread()) //观察者事件切到子线程执行
        .subscribe(observer); //订阅事件

log打印如下:

2021-03-27 10:53:45.697 7130-7130/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onSubscribe: 
2021-03-27 10:53:45.699 7130-7169/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: subscribe: 
2021-03-27 10:53:45.700 7130-7170/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onNext: s=hello
2021-03-27 10:53:45.700 7130-7170/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onNext: s=world
2021-03-27 10:53:45.700 7130-7170/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onComplete:

为了便于观察,上面将观察者和被观察者分开创建,后面指定被观察者事件线程在io线程处理,观察者事件在子线程处理,最后通过subscribe方法使二者产生订阅关系。通过根据log可以看到,虽然观察者事件被指定在子线程处理,但是observer 的onSubscribe方法仍然在主线程执行,这就说明onSubscribe方法不受observeOn方法的影响,Observer和observable的其他方法都按照指定在子线程执行。

1、observable的创建

Observable.create会在ObservableCreate被观察者对象

//ObservableCreate.java
public final class ObservableCreate<T> extends Observable<T> {
    final ObservableOnSubscribe<T> source;

    public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source; //观察者对象,具体实现在Observable.create中传入
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer); //创建被观察者
        observer.onSubscribe(parent); //被观察者的onSubscribe方法被调用

        try {
            source.subscribe(parent); //观察者的subscribe方法被调用
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

subscribeActual方法是实际订阅时调用的具体实现,该方法传入了被观察者,在方法里面被观察者对象的onSubscribe被调用,然后被观察者对象的subscribe方法开始执行,在里面通过emitter.onNext("hello")、emitter.onComplete()等方法最终调用观察者对象的onNext、onComplete等方法。这就是为什么之前说到onSubscribe方法不受observeOn方法的影响,因为被观察者对象的onSubscribe方法调用时,被观察者事件还没开始发送呢,谈何线程切换。

2、Observer的创建

Observer的创建比较简单,就是创建了一个Observer接口实现,在接口方法onSubscribe、onNext、onComplete、onError方法中事件自己的逻辑。

3、被观察者线程切换subscribeOn

首先看下Schedulers.io()的具体实现

//Schedulers.java
……
static final class IoHolder {
    static final Scheduler DEFAULT = new IoScheduler();//一个单例IoScheduler
}
……
//IoScheduler.java
public final class IoScheduler extends Scheduler {
    ……
    static {
    ……
    NONE = new CachedWorkerPool(0, null, WORKER_THREAD_FACTORY);
    NONE.shutdown();
……
    static final class CachedWorkerPool implements Runnable {
    private final long keepAliveTime;
    private final ConcurrentLinkedQueue<ThreadWorker> expiringWorkerQueue;
    final CompositeDisposable allWorkers;
    private final ScheduledExecutorService evictorService;
    private final Future<?> evictorTask;
    private final ThreadFactory threadFactory;
    ……
static final class CachedWorkerPool implements Runnable {
    ……
    CachedWorkerPool(long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) {
        this.keepAliveTime = unit != null ? unit.toNanos(keepAliveTime) : 0L;
        this.expiringWorkerQueue = new ConcurrentLinkedQueue<ThreadWorker>();
        this.allWorkers = new CompositeDisposable();
        this.threadFactory = threadFactory;

        ScheduledExecutorService evictor = null;
        Future<?> task = null;
        if (unit != null) {
            //周期性线程池
            evictor = Executors.newScheduledThreadPool(1, EVICTOR_THREAD_FACTORY);
            task = evictor.scheduleWithFixedDelay(this, this.keepAliveTime, this.keepAliveTime, TimeUnit.NANOSECONDS);
        }
        evictorService = evictor;
        evictorTask = task;
    }
    
    ……
    ThreadWorker get() {//获取线程执行者
    if (allWorkers.isDisposed()) {
        return SHUTDOWN_THREAD_WORKER;
    }
    while (!expiringWorkerQueue.isEmpty()) {
        ThreadWorker threadWorker = expiringWorkerQueue.poll();
        if (threadWorker != null) {
            return threadWorker;
        }
    }

    // No cached worker found, so create a new one.
    ThreadWorker w = new ThreadWorker(threadFactory); //如果没有线程执行者则创建
    allWorkers.add(w);
    return w;
}
//NewThreadWorker.java,上面的ThreadWorker继承自NewThreadWorker
public class NewThreadWorker extends Scheduler.Worker implements Disposable {
    private final ScheduledExecutorService executor;//周期性线程服务

    volatile boolean disposed;

    public NewThreadWorker(ThreadFactory threadFactory) {
        executor = SchedulerPoolFactory.create(threadFactory);
    }

根据上面的代码走读片段可以看到Schedulers.io()就是一个核心数为1的周期性线程池。

subscribeOn创建了一个ObservableSubscribeOn被观察者对象,在构造函数中将上游的被观察者和线程调度器传递进来,这里需要注意下游的被观察者构建时会将最近的上游被观察者作为参数传过来,那么这样一层层向上追溯,最后会调到第一个被观察者。

//Observable.java
public final Observable<T> subscribeOn(Scheduler scheduler) {
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

被观察者在实际订阅的时候调用观察者的setDisposable方法,这里就用到了传过来的线程调度器去执行一个异步操作。

//ObservableSubscribeOn.java
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source); //设置上游被观察者
        this.scheduler = scheduler; //指定线程调度
    }

    @Override
    public void subscribeActual(final Observer<? super T> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent);

        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }

看下SubscribeTask的具体实现可以看到执行了上游被观察者的ubscribe方法,根据上面提到的每个下游被观察者都带有邻近的上游被观察者作为参数,那么层层上溯,这里的source会是第一个被观察者,这就解释了为什么多次调用subscribeOn方法为什么只有第一次subscribeOn指定的线程调度器有效。

//ObservableSubscribeOn.java
final class SubscribeTask implements Runnable {
    private final SubscribeOnObserver<T> parent;

    SubscribeTask(SubscribeOnObserver<T> parent) {
        this.parent = parent;
    }

    @Override
    public void run() {
        source.subscribe(parent);//上游被观察者的subscribe方法执行
    }
}

4、观察者线程切换observeOn

observeOn具体会创建一个ObservableObserveOn被观察者对象,在该对象中创建一个带有指定线程调度的观察者对象。

//ObservableObserveOn.java
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;
    final boolean delayError;
    final int bufferSize;
    public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler; //指定的线程调度
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) { //TrampolineScheduler是当前线程串行消费的调度模型
            source.subscribe(observer);
        } else {
            Scheduler.Worker w = scheduler.createWorker();
            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));//将指定的线程调度器作为参数创建新的观察者
        }
    }

创建新的观察者对象是ObservableObserveOn.java中的一个内部类ObserveOnObserver

//ObservableObserveOn$ObserveOnObserver.java
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
implements Observer<T>, Runnable {
……
    ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean delayError, int bufferSize) {
        this.actual = actual;
        this.worker = worker;
        this.delayError = delayError;
        this.bufferSize = bufferSize;
    }

    ……

    @Override
    public void onNext(T t) {
        if (done) {
            return;
        }

        if (sourceMode != QueueDisposable.ASYNC) {
            queue.offer(t);
        }
        schedule();
    }

    @Override
    public void onError(Throwable t) {
        if (done) { //done来限制onError和onComplete方法不会都执行
            RxJavaPlugins.onError(t);
            return;
        }
        error = t;
        done = true;
        schedule();
    }

    @Override
    public void onComplete() {
        if (done) {//done来限制onError和onComplete方法不会都执行
            return;
        }
        done = true;
        schedule();
    }
……
    void schedule() {
        if (getAndIncrement() == 0) {
            worker.schedule(this); //根据特定的线程调度器执行相应的任务
        }
    }
}

从onNext、onError、onComplete的具体实现可以看出onError和onComplete方法不会都执行,如果onError和onComplete方法已经执行了那么也不会再执行onNext方法。在这三个方法中都调用了schedule()方法,schedule()方法就会调用具体的线程调度器执行任务了,所以只需要在订阅前通过指定observeOn指定线程,那么onNext、onError、onComplete就会在指定的线程执行。

看下AndroidSchedulers.mainThread()的具体实现,通过mainThread()方法最终获得了DEFAULT 主线程调取器,实质上还是通过handler进行线程切换。

//AndroidSchedulers.java
public final class AndroidSchedulers {

    private static final class MainHolder {

        static final Scheduler DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()));//获取主线程looper创建主线调度器
    }

    private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
            new Callable<Scheduler>() {
                @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);
    }

    /** A {@link Scheduler} which executes actions on {@code looper}. */
    public static Scheduler from(Looper looper) {
        if (looper == null) throw new NullPointerException("looper == null");
        return new HandlerScheduler(new Handler(looper));
    }

    private AndroidSchedulers() {
        throw new AssertionError("No instances.");
    }
}
//HandlerScheduler.java
final class HandlerScheduler extends Scheduler {
    private final Handler handler;

    HandlerScheduler(Handler handler) {
        this.handler = handler;
    }

    @Override
    public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) {
        if (run == null) throw new NullPointerException("run == null");
        if (unit == null) throw new NullPointerException("unit == null");

        run = RxJavaPlugins.onSchedule(run);
        ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
        handler.postDelayed(scheduled, Math.max(0L, unit.toMillis(delay)));//使用主线程handler将任务切到主线程
        return scheduled;
    }

这里需要注意observeOn会对下游数据起作用,如果有连续多个observeOn则下游事件以上游最近一次observeOn设置的线程调度为准;如果没有observeOn设置线程调度,那么下游事件线程与被观察者执行线程保持一致。修改上面的订阅流程,观察者和被观察代码保持不变。

observable
        .filter(new Predicate<String>() {
            @Override
            public boolean test(String s) throws Exception {
                Log.d(TAG, "filter: o="+s);
                return s.equalsIgnoreCase("world");
            }
        })
        .subscribeOn(Schedulers.io())
        .flatMap(new Function<String, Observable<String>>() {
            @Override
            public Observable<String> apply(String s) {
                Log.d(TAG, "flatMap: ");
                return Observable.just(s+System.currentTimeMillis());
            }
        })
        .observeOn(AndroidSchedulers.mainThread())
        .map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) throws Exception {
                Log.d(TAG, "map: ");
                return s.length();
            }
        })
        .subscribe(observer);

日志打印如下:

2021-04-03 16:38:53.225 14221-14221/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onSubscribe: 
2021-04-03 16:38:53.229 14221-14269/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: subscribe: 
2021-04-03 16:38:53.229 14221-14269/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: filter: o=hello
2021-04-03 16:38:53.230 14221-14269/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: filter: o=world
2021-04-03 16:38:53.230 14221-14269/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: flatMap: 
2021-04-03 16:38:53.282 14221-14221/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: map: 
2021-04-03 16:38:53.282 14221-14221/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onNext: s=18
2021-04-03 16:38:53.282 14221-14221/com.zhanxun.myapplication.car.debug D/MainActivity2Tag: onComplete: 

猜你喜欢

转载自blog.csdn.net/u013795543/article/details/115418737