Rx线程切换原理

346 阅读2分钟

subscribeOn() 源码分析

给上面的代码分配线程

 Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("AAA");
            }
        })
   							//ObservableCreate.subscribeOn
                .subscribeOn(Schedulers.io())
   								//SubscribeOnObserver.subscribe
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        
                    }

                    @Override
                    public void onNext(String s) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

点进Schedulers.io() 看看到底做了什么?

 IO = RxJavaPlugins.initIoScheduler(new IOTask());

初始化的时候传入了 new IOTask() 继续往里面跟,其实这里面就是一个线程池。

就是这样一种流程,我们再来看.subscribe 其实也就相当于是SubscribeOnObserver.subscribe,点进去看看 其实这个流程和前面分析的流程都是一样的 最终会走到

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

又是一个包裹 然后传给new SubscribeTask()

 final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

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

        @Override
        public void run() {
            source.subscribe(parent);
        }
    }

毋庸置疑SubscribeTask这段代码肯定会抛给线程池来执行的

我们来看下整体的流程

可以看到线程池执行完任务之后都是异步 到终点也是异步 显然是不行的。所以需要切换到主线程。

ObserveOn() 源码分析

给下面的代码分配线程

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("AAA");
            }
        })
   							//ObservableCreate.subscribeOn
                .subscribeOn(Schedulers.io())
    						 .observeOn(AndroidSchedulers.mainThread())
   								//observeOnObserver.subscribe
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        
                    }

                    @Override
                    public void onNext(String s) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });


加上 .observeOn(AndroidSchedulers.mainThread()) 就可以切换主线程了,我们看下怎么做的

还是一样的流程 看源码,先看AndroidSchedulers.mainThread() 最终返回的是Scheduler MAIN_THREAD,

大概流程 是这样的 Scheduler MAIN_THREAD ----> DEFAULT = new HandlerScheduler(new Handler(Looper.getMainLooper()))--->HandlerScheduler$HandlerWorker schedule{ handler.sendMessageDelayed(run) } 这段伪代码就是大概的流程了

自定义操作符

明白了整个思想和流程之后 ,依葫芦画瓢自定义操作符就很简单了,我们来自定义一个防抖的操作符

首先 定以一个 RxView类 里面有一个静态方法(操作符)

public class RxView {
    public static Observable<Object> clicks(View view) {
        return new ViewClickObservable(view);
    }
}
public class ViewClickObservable extends Observable<Object> {

    private final View view;
 		private static final Object EVENT = new Object();
    public ViewClickObservable(View view) {
        this.view = view;
    }

    @Override
    protected void subscribeActual(Observer<? super Object> observer) {
        // 可以干自己的事情
        MyListener myListener = new MyListener(view, observer);
        observer.onSubscribe(myListener);

        this.view.setOnClickListener(myListener);
    }

    // 包裹
    static final class MyListener implements View.OnClickListener, Disposable {

        private final View view;
        private Observer<Object> observer;

        private final AtomicBoolean isDisposable = new AtomicBoolean();

        public MyListener(View view, Observer<Object> observer) {
            this.view = view;
            this.observer = observer;

        }

        @Override
        public void onClick(View v) {
            if (isDisposed() == false) {
                observer.onNext(EVENT);
            }

        }
        @Override
        public void dispose() {
            if (isDisposable.compareAndSet(false, true)) {
                if (Looper.myLooper() == Looper.getMainLooper()) {
                    view.setOnClickListener(null);

                } else { 
                    AndroidSchedulers.mainThread().scheduleDirect(new Runnable() {
                        @Override
                        public void run() {
                            view.setOnClickListener(null);
                        }
                    });
                }
            }
        }

        @Override
        public boolean isDisposed() {
            return isDisposable.get();
        }
    }
}

现在就可以正常使用了 其实就是仿写了