RxJava 原理分析(一)订阅关系的形成

最近复习RxJava的时候发现解说RxJava的原理不多,所以,来机智的骗心心来了。

依赖:

implementation "io.reactivex.rxjava2:rxjava:2.2.4"

简单使用

待会儿讲解的原理呢,是由这个使用 demo 来讲解。

        Observable.create(new ObservableOnSubscribe<Integer>() {  // 创建被观察者
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);   // 发射器,发射一个事件
                emitter.onNext(2);
            }
        }).subscribe(new Consumer<Integer>() {  // 观察者
            @Override
            public void accept(Integer integer) throws Exception {  // 用于处理 onNext 事件
                Log.d(TAG, "accept: "+integer);
            }
        }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.d(TAG, "accept: "+throwable.getMessage());
                    }
                });

原理解析

Observable.create(ObservableOnSubscribe<T>)

在上面的使用demo中,这是整个订阅过程的开始:创建一个被观察者。来,我们看一下我们的被观察者是什么。

Observable.class

    @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));  // 默认直接返回这个new出来的ObservableCreate
    }

这个ObjectHelper.requireNonNull怎么判空啊?

    public static <T> T requireNonNull(T object, String message) {
        if (object == null) {
            throw new NullPointerException(message);
        }
        return object;
    }

简直不要太简单,就是判断输入的object是不是null,不是就返回,是就抛出异常。

那这个RxJavaPlugins又是干嘛的呢?用过的都知道,没用过推荐看一下给初学者的RxJava2.0教程(十) 。其实我们没有对这个 RxJavaPlugins 做设置的话,就是返回我们传进来的这个参数。后面我们看到这个RxJavaPlugins就可以默认为直接返回参数。

书接上文,那调用 Observable.create(ObservableOnSubscribe) ,岂不是就是把自己在外部实现的 ObservableOnSubscribe 匿名内部类包装到 ObservableCreate 中去罗。

public final class ObservableCreate<T> extends Observable<T> {  // 注意继承关系哦
    final ObservableOnSubscribe<T> source;  // 最原始的目标:被观察者

    public ObservableCreate(ObservableOnSubscribe<T> source) { 
        this.source = source;  // 传进来的是外面new的匿名内部类ObservableOnSubscribe
    }
...
}

看到这里,emmm,nice,保存住了被观察者,返回了ObservableCreate 对象。注意哦,这个时候后面一个 . 操作的就是这个 ObservableCreate对象(换言之,后面点的就是ObservableCreate中的方法)。

好的,下面就是 .subscribe

.subscribe

这个方法就很有意思了,实现了订阅这个操作,或者说,是触发了onSuscribe、onNext 等操作。

先看一下 subscribe 这个方法的重载:

    public final Disposable subscribe() {}   // 注意哦,这里的都是final方法
    public final Disposable subscribe(Consumer<? super T> onNext) {}
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {} 
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete) {}
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe) {}
    public final void subscribe(Observer<? super T> observer) {}

有点多哈,但是实现呢?很简单,大家都调用最后一个处理,没有传参的都添上默认的 Custom 就可以了。什么叫默认实现,就是实现了接口,但是默认不处理,比如默认的Action,还有就是简单处理,比如onError,但是都不是很重要,我们主要关注我们自己实现的东西嘛。

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {
        return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
            Action onComplete, Consumer<? super Disposable> onSubscribe) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");  // 挨个判空
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");

        LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);  // 用一个类来包裹

        subscribe(ls);  // 包裹类的订阅

        return ls;
    }

那么这个用来包裹的 LambdaObserver 又是什么鬼呢?

public final class LambdaObserver<T> extends AtomicReference<Disposable>
        implements Observer<T>, Disposable, LambdaConsumerIntrospection {

    private static final long serialVersionUID = -7251123623727029452L;
    final Consumer<? super T> onNext;
    final Consumer<? super Throwable> onError;
    final Action onComplete;
    final Consumer<? super Disposable> onSubscribe;

    public LambdaObserver(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
            Action onComplete,
            Consumer<? super Disposable> onSubscribe) {
        super();
        this.onNext = onNext;
        this.onError = onError;
        this.onComplete = onComplete;
        this.onSubscribe = onSubscribe;
    }
...
}

就是将四个类型(onNext,onError,onComplete,onSubscribe)封装成一个一个对象,方便对整个流程的调用。

将四个对象封装在一起了过后,就是应该是订阅了把?


    @SchedulerSupport(SchedulerSupport.NONE)
    @Override
    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);  // 检查需要执行预操作不,默认返回 observer
            // 判空
            ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");
    
            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);  // 错误的话,捕获,并交给RxJavaPlugins#onError来处理,没有交给我们自定义的onError,莫看错啦

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

真正有用的就是 subscribeActual(observer);这一句,吐血哦,还不订阅,我都快等不及了。好嘛,大神就是大神,一看,自己没实现。后面一想,就是牛逼。

    /**
     * Operator implementations (both source and intermediate) should implement this method that
     * performs the necessary business logic and handles the incoming {@link Observer}s.
     * <p>There is no need to call any of the plugin hooks on the current {@code Observable} instance or
     * the {@code Observer}; all hooks and basic safeguards have been
     * applied by {@link #subscribe(Observer)} before this method gets called.
     * @param observer the incoming Observer, never null
     */
    protected abstract void subscribeActual(Observer<? super T> observer);

所有的操作符都会重写这个方法,我是不是暴露了什么,emm,所有运算符返回都是 Observable 的子类,就比如说 create 返回的就是 Observable 的子类 ObservableCreate,后面就是在这基础上调用了。这里我们可以看到,其实所有的 subscribe 我们都重写不了,唯一能重写且必须重写的就是这个 subscribeActual。这就意味着,这个方法是我子类实现真正订阅的入口。

前面讲解我们知道,现在在demo中调用的是 ObservableCreate 的 subscribe,那么事情就变得很简单,我们直接找到 ObservableCreate#subscribeActual(observer) 进行分析就好。在分析之前,先用图总结下前面的东西:


好的嘞,那我们接下来就看一下核心的 subscribeActual 方法如何实现的?

    @Override
    protected void subscribeActual(Observer<? super T> observer) {  //传进来的就是前面的 LambdaObserver
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);  // 发射器,每一个操作符对应的类内部都会自己实现,因为处理逻辑不一样啊
        observer.onSubscribe(parent);  // 回调了自己实现的 onSubscribe 对用的Consumer

        try {
            source.subscribe(parent);   // 这个source就是初始化类的时候传进来的被观察者,这里将发送器给了它
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);  // 这里捕获的异常才交给自己写的Consumer处理
        }
    }

这里代码不多,干的事还不少,首先是new出我们的发射器,然后触发被观察者的订阅回调,然后再,执行被观察者的subscribe方法,如果捕获到异常就交给自定义的 onError 处理。

有一个概念可以先了解,无论以后把这个对象怎么包裹,传递,只有这里才调用了被观察者 Observable 的 subscribe 方法。

接下来我们来详解一下,这个回调流程。
observer.onSubscribe(parent); 这里的 observer 是什么?传进来的 包装有自定义的观察者的 LambdaObserver ,他是 Observable 的子类。接下来看一下他的调用:

    @Override
    public void onSubscribe(Disposable d) {
        if (DisposableHelper.setOnce(this, d)) {  // 设置并判断是否是第一次
            try {
                onSubscribe.accept(this);
            } catch (Throwable ex) {
                Exceptions.throwIfFatal(ex);
                d.dispose();   // 出现异常,解除订阅
                onError(ex);   // 并向下传递
            }
        }
    }

    @Override
    public void onError(Throwable t) {
        if (!isDisposed()) {   // 判断是否断开连接
            lazySet(DisposableHelper.DISPOSED);
            try {
                onError.accept(t);   //交给自定义的消费者
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                RxJavaPlugins.onError(new CompositeException(t, e));
            }
        } else {
            RxJavaPlugins.onError(t);
        }
    }

很简单,对不对,就是直接调用了 onNext 消费者的 accept 方法(自定义或者默认)。出现异常,如果没有断开连接,且是第一次接收到,就交给 onError (自定义或者默认)处理。

那么 source.subscribe(parent);不会也这么简单把?
source 就是传进来的 ObservableOnSubscribe,自定义的被观察者
parent 就是发射器。这一调用,我们自己写的被观察者的逻辑就巴拉巴拉的执行了

这里就是直接就回调了。吓人。。

parent.onError(ex); 怎么实现的?这就要真正说道说道这个发射器了。

发送器是什么狗东西呢?它是ObservableCreate的静态内部类:

    static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {

        final Observer<? super T> observer;  // 观察者,就是传进来的 LambdaObserver

        CreateEmitter(Observer<? super T> observer) {
            this.observer = observer;  
        }

        @Override
        public void onNext(T t) {  
            if (t == null) {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
            if (!isDisposed()) {   // 是否已经断开连接
                observer.onNext(t);  // 调用自定义的Custom回调处理
            }
        }

        @Override
        public void onError(Throwable t) { 
            if (!tryOnError(t)) {  // 交给观察者
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public boolean tryOnError(Throwable t) {
            if (t == null) {
                t = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
            }
            if (!isDisposed()) {  //没断开,不为null
                try {
                    observer.onError(t);
                } finally {
                    dispose();  //失败直接断开连接
                }
                return true;
            }
            return false;
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();  // 交给观察者
                } finally {
                    dispose();
                }
            }
        }

        @Override
        public void setDisposable(Disposable d) {   DisposableHelper.set(this, d);   }

        @Override
        public void dispose() {    DisposableHelper.dispose(this);    }

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

    }

咦,这结构简直不要太简单,就相当于一次中转,只不过是加入了一些容错机制。到这里整个流程要用到的类就结束了,当我们在书写被观察者的时候,使用这个发射器提交东西,就是直接调用这个东西来调用消费者的对应回调。

千言不如一图


不对,放错了


  1. 创建真正的被观察者包裹对象(继承于 Observable),并将自己写的真正被观察者包裹起来
  2. 调用被观察者的subscribe方法,将自己创建的观察者包裹起来
  3. 作为参数,传入ObservableCreate 对方实现的 subscribeActual(Observer) 中。
  4. 在 subscribeActual 方法中生成 emitter,并且回调被观察者的onSubscribe,确定连接关系。
  5. 自己写的被观察者的 subscribe 调用,我们可以使用 emitter 提交东西,一提交就将提交的东西交给 被观察者对应的方法执行
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容