Rx模式以及map原理

538 阅读4分钟

观察者模式

Rx的设计模式其实就是一种变相的 观察者模式,所以我们必须得先了解下标准的观察者模式

这就是标准的观察者模式。很简单

Rx Hook

问题:如果我的整个项目都使用了Rxjava ,那么我怎么监听全局Rx呢

首先看一段代码:

 Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                
            }
        })
                .map(new Function<String, String>() {
                    @Override
                    public String apply(String s) throws Exception {
                        return null;
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable = d;
                    }

                    @Override
                    public void onNext(String s) {
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {
                    }
                });

代码没啥好说的,很简单,我们在 .create  的时候会给我们返回一个new ObservableCreate,在 .map的时候返回的是new ObservableMap ....我们需要的就是在这个过程中拦截。如图

那么中间区域到底是什么呢?我们来看下源码 ?点进create 发现

 		@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }

中间区域 就是 onAssembly 也就是我们的全局hook 如果点进map 也是一样的

 		@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

点进onAssembly 进去

public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
        Function<? super Observable, ? extends Observable> f = 			  onObservableAssembly;
        if (f != null) {
            return apply(f, source);
        }
        return source;
      

onObservableAssembly 默认为null 所以这个相当于啥都没做。。。 那我们在跟一下onObservableAssembly 赋值的地方看一下

  /**
     * Sets the specific hook function.
     * @param onObservableAssembly the hook function to set, null allowed
     */
    @SuppressWarnings("rawtypes")
    public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) {
        if (lockdown) {
            throw new IllegalStateException("Plugins can't be changed anymore");
        }
        RxJavaPlugins.onObservableAssembly = onObservableAssembly;
    }

看注释写的很清楚 设置指定的hook函数 所以 只要我们调用这个函数 设置我们自己的function就可以实现拦截全局的rx了

RxJavaPlugins.setOnObservableAssembly(new Function<Observable, Observable>() {
            @Override
            public Observable apply(Observable observable) throws Exception {
                //这里就可以拦截了
                //返回null的话 会导致后面所有用到rx的地方空指针
                return observable;
            }
        });
        

Rx 观察者模式

分为三步 第一、创建Observable,第二、创建Observer、第三、使用subcribe()订阅

首先看Observer源码

public interface Observer<T> {

    /**
     * Provides the Observer with the means of cancelling (disposing) the
     * connection (channel) with the Observable in both
     * synchronous (from within {@link #onNext(Object)}) and asynchronous manner.
     * @param d the Disposable instance whose {@link Disposable#dispose()} can
     * be called anytime to cancel the connection
     * @since 2.0
     */
    void onSubscribe(@NonNull Disposable d);

    /**
     * Provides the Observer with a new item to observe.
     * <p>
     * The {@link Observable} may call this method 0 or more times.
     * <p>
     * The {@code Observable} will not call this method again after it calls either {@link #onComplete} or
     * {@link #onError}.
     *
     * @param t
     *          the item emitted by the Observable
     */
    void onNext(@NonNull T t);

    /**
     * Notifies the Observer that the {@link Observable} has experienced an error condition.
     * <p>
     * If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
     * {@link #onComplete}.
     *
     * @param e
     *          the exception encountered by the Observable
     */
    void onError(@NonNull Throwable e);

    /**
     * Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
     * <p>
     * The {@link Observable} will not call this method if it calls {@link #onError}.
     */
    void onComplete();

}

可以看到 就是一个接口而已,真正的实现 是我们的实现的

看Observable的源码

刚才已经看过了Observable.create源码了

		@CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
    }
    

可以看到 传入的参数 就是我们传入的自定义的source

订阅流程分析

点进subscribe() 可以看到

 @SchedulerSupport(SchedulerSupport.NONE)
    @Override
    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);

            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");

            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // can't call onError because no way to know if a Disposable has been set or not
            // can't call onSubscribe because the call might have set a Subscription already
            RxJavaPlugins.onError(e);

            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
            npe.initCause(e);
            throw npe;
        }
    }

可以看到里面的 有效代码只有 subscribeActual(observer); 点进去发现 这是个抽象方法,由于.subscribe() 实际上是ObservableCreate. subscribe() 的,create一执行完成就会返回ObservableCreate对象。 所以 subscribeActual的实现肯定在ObservableCreate

 @Override
    protected void subscribeActual(Observer<? super T> observer) {
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        observer.onSubscribe(parent);

        try {
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

可以看到 new了一个发射器包装了我们传进来的observer 然后自定义的source调用了 subscribe(),这样两端就联系起来了,看下整体流程

整体就是一个U型的结构

两者的区别

普通的观察者模式: 一个被观察者 对应多个观察者 被观察者发出改变通知 所有的观察者改变

Rx的观察者模式:多个被观察者对应一个观察者 并且需要起点和终点再订阅一次之后 才发出通知改变,终点才改变

map操作符的原理

示例代码:

  			// ObseravbleCreate  自定义source传递进去了 == source
        Observable.create(
                // 自定义source
                new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> e) throws Exception {

                    }
        })
         //  ObseravbleCreate.map
        .map(new Function<String, Bitmap>() {
            @Override
            public Bitmap apply(String s) throws Exception {
                return null;
            }
        })
        // ObservableMap.subscribe
        .subscribe(
                // 自定义观察者(终点)
                new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Bitmap bitmap) {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

同样的 我们来看下流程

可以看到 和订阅流程类似 只是多了一个 封包裹 和拆包裹的过程

这是一个洋葱模型 (封包裹-> 拆包裹)

事实上Rx还用了一个装饰模式

大概就是这样的模型

那么其实 Rx也不算是标准的u型结构 而是:

类似于下单买东西--->封包裹--->拆包裹