RxJava 2.x 源码分析(一) 分发订阅流程

本文深入探讨RxJava2.x的数据分发和接收流程,包括Observable如何分发数据以及Observer如何订阅。同时,文章详细阐述了RxJava如何通过Disposable实现取消订阅,确保Observer能中断数据接收。内容涵盖了ObservableCreate的构造、subscribe过程以及Disposable的dispose方法在取消订阅中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文将讲解两个知识点

1.RxJava的数据分发和接收流程,即Observable(可观察者)如何分发数据和Observer(观察者)如何订阅数据

2.RxJava是如何通过Disposable来取消订阅的,让Observer中断接收Observable分发的数据

一:RxJava2.x的数据分发和接收

通过一个简单的例子来看看RxJava的使用

         //1.为了方便理解,下面的代码可以这样理解,其中Observable是一个抽象可观察者,通过
         //create方法创建一个真正的可观察者,其中参数ObservableOnSubscribe可以理解为
         //可观察者的数据发射源,Integer是发射数据的类型
         //2.下面的subscribe方法将触发可观察者的行为,参数Observer是一个原始的
         //观察者,它将订阅可观察者发射的数据
         Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
                mRxOperatorsText.append("Observable emit 1" + "\n");
                Log.d(TAG, "Observable emit 1" + "\n");
                e.onNext(1);
                mRxOperatorsText.append("Observable emit 2" + "\n");
                Log.d(TAG, "Observable emit 2" + "\n");
                e.onNext(2);
                mRxOperatorsText.append("Observable emit 3" + "\n");
                Log.d(TAG, "Observable emit 3" + "\n");
                e.onNext(3);
                mRxOperatorsText.append("Observable emit 4" + "\n");
                Log.d(TAG, "Observable emit 4" + "\n" );
                e.onNext(4);
            }
        }).subscribe(new Observer<Integer>() {
            private int i;
            private Disposable mDisposable;

            @Override
            public void onSubscribe(@NonNull Disposable d) {
                mRxOperatorsText.append("onSubscribe : " + d.isDisposed() + "\n");
                Log.d(TAG, "onSubscribe : " + d.isDisposed() + "\n" );
                mDisposable = d;
            }

            @Override
            public void onNext(@NonNull Integer integer) {
                mRxOperatorsText.append("onNext : value : " + integer + "\n");
                Log.d(TAG, "onNext : value : " + integer + "\n" );
            }

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

            @Override
            public void onComplete() {
                mRxOperatorsText.append("onComplete" + "\n");
                Log.d(TAG, "onComplete" + "\n" );
            }
        });

输出结果如下:

RxJava框架的设计是基于一个观察者模式,例子中create方法创建的可观察者属于原始可观察者,它持有一个数据发射源,然后观察者通过订阅便可以接收到可观察者发射的数据,这些属于设计思想的范畴,下面来看看源码是如何实现的

1.创建可观察者


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

create方法返回一个ObservableCreate实例,它属于真正的可观察者,而Observable是抽象的可观察者,构造函数接收的source为数据发射源,由ObservableOnSubscribe接口实现

public interface ObservableOnSubscribe<T> {

    void subscribe(@NonNull ObservableEmitter<T> e) throws Exception;
}

subscribe是我们要实现的接口方法,接收一个ObservableEmitter参数,这个参数可以理解为数据发射器,此接口有如下方法

public interface ObservableEmitter<T> extends Emitter<T> {

    void setDisposable(@Nullable Disposable d);

    void setCancellable(@Nullable Cancellable c);

    boolean isDisposed();

    @NonNull
    ObservableEmitter<T> serialize();
}

public interface Emitter<T> {

    void onNext(@NonNull T value);

    void onError(@NonNull Throwable error);

    void onComplete();
}

可以看到几个常用的方法,来看看可观察者ObservableCreate的构造函数

 public ObservableCreate(ObservableOnSubscribe<T> source) {
        this.source = source;
    }

看到可观察者将持有数据发射源的引用,可以肯定的是,可观察者就是通过这个source来发射数据的

 

2.可观察者接受订阅行为,将触发数据的发射

    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);
            RxJavaPlugins.onError(e);

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

subscribe方法可以理解为可观察者接受订阅,参数是一个观察者,然后调用subscribeActual,这是在Observable中的一个抽象方法,我们去看ObservableCreate中是如何实现的

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        //创建一个数据发射器,参数为观察者
        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //首先调用观察者的onSubscribe方法,代表观察者实现订阅,
        observer.onSubscribe(parent);

        try {
            //执行数据发射源的subscribe方法,传参数据发射器,这个发射源source就是例子中我们
            //实现的ObservableOnSubscribe接口,此时代表可观察者开始发射数据了
            source.subscribe(parent);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            parent.onError(ex);
        }
    }

可以看到,发射源进行数据的发射最终由发射器来执行,发射器持有原始观察者的引用,来看看发射器是如何实现的

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


        private static final long serialVersionUID = -3434801548987643227L;
        //数据接收者
        final Observer<? super T> observer;

        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()) {
                //回调接收者的onNext方法
                observer.onNext(t);
            }
        }

        @Override
        public void onError(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()) {
                try {
                    observer.onError(t);
                } finally {
                    dispose();
                }
            } else {
                RxJavaPlugins.onError(t);
            }
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }

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

        @Override
        public void setCancellable(Cancellable c) {
            setDisposable(new CancellableDisposable(c));
        }

        @Override
        public ObservableEmitter<T> serialize() {
            return new SerializedEmitter<T>(this);
        }

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

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

发射器中实现的方法有onNext、onError、onComplete等等,比如onNext方法中,首先判断发射的数据不能为null,否则抛出异常,然后通过isDisposed判断数据的接收是否被中断,如果没有则调用接收者的onNext方法接收数据

发射器还实现Disposable接口,此接口有两个方法:dispose和isDisposed方法,接收者可调用dispose方法中断数据的接收,接收者可以在onSubscribe中获得Disposed,这也是为什么发射数据之前要先调用接收者的onSubscribe方法,将Disposed传递给它

到这里我们明白RxJava中的一个最简单的数据分发和接收原理,为什么说是最简单呢,因为这里只包含了一个可观察者和观察者,即原始可观察者和原始观察者,而在实际应用中,整个过程可能会有多个可观察者和观察者串联在一起,这将复杂很多,在后面的文章会看到

 

二:RxJava 2.x中取消订阅的原理

RxJava中可以通过Disposable的dispose方法来取消数据的订阅,取消订阅以后Observer就不再接收到上游数据,但只是接收者不接收,发射者还是照样发射的,如下

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
                mRxOperatorsText.append("Observable emit 1" + "\n");
                Log.d(TAG, "Observable emit 1" + "\n");
                e.onNext(1);
                mRxOperatorsText.append("Observable emit 2" + "\n");
                Log.d(TAG, "Observable emit 2" + "\n");
                e.onNext(2);
                mRxOperatorsText.append("Observable emit 3" + "\n");
                Log.d(TAG, "Observable emit 3" + "\n");
                e.onNext(3);
                //e.onComplete();
                mRxOperatorsText.append("Observable emit 4" + "\n");
                Log.d(TAG, "Observable emit 4" + "\n" );
                e.onNext(4);
            }
        }).subscribeOn(Schedulers.io()) //切换到io线程
                .observeOn(AndroidSchedulers.mainThread()) //切换到主线程
                .subscribe(new Observer<Integer>() {
            private int i;
            private Disposable mDisposable;

            @Override
            public void onSubscribe(@NonNull Disposable d) {
                mRxOperatorsText.append("onSubscribe : " + d.isDisposed() + "\n");
                Log.d(TAG, "onSubscribe : " + d.isDisposed() + "\n" );
                mDisposable = d;
            }

            @Override
            public void onNext(@NonNull Integer integer) {
                mRxOperatorsText.append("onNext : value : " + integer + "\n");
                Log.d(TAG, "onNext : value : " + integer + "\n" );
                i++;
                if (i == 2) {
                    // 在RxJava 2.x 中,新增的Disposable可以做到切断的操作,让Observer观察者不再接收上游事件
                    mDisposable.dispose();
                    mRxOperatorsText.append("onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
                    Log.d(TAG, "onNext : isDisposable : " + mDisposable.isDisposed() + "\n");
                }
            }

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

            @Override
            public void onComplete() {
                mRxOperatorsText.append("onComplete" + "\n");
                Log.d(TAG, "onComplete" + "\n" );
            }
        });

在Observer的onNext方法中,当接收到第二个数据的时候,调用Disposable的dispose取消订阅,来看看输出结果

发射者一共发射了四个数字,接收者只接收到前面两个数字,那是因为在接收到第二个数字的时候,用Disposed中断了数据的接收

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

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

调用了DisposableHelper的dispose方法,其中DisposableHelper是一个枚举类,来看看它的dispose方法

    public static boolean dispose(AtomicReference<Disposable> field) {
        Disposable current = field.get();
        Disposable d = DISPOSED;
        if (current != d) {
            current = field.getAndSet(d);
            if (current != d) {
                if (current != null) {
                    current.dispose();
                }
                return true;
            }
        }
        return false;
    }

参数是CreateEmitter,因为CreateEmitter继承了AtomicReference,其实AtomicReference保存Disposable的引用,属于线程安全的原子操作。上面方法中,DISPOSED是枚举DisposableHelper的一个单例,其实就是将DISPOSED单例保存到AtomicReference<Disposable>中

在判断当前接收有没有被中断时候调用isDisposed,然后是DisposableHelper.isDisposed(get()),其实是判断当前AtomicReference中有没有保存DISPOSED单例,有代表已经中断接收数据了,否则没有,如下

 

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

        public static boolean isDisposed(Disposable d) {
        return d == DISPOSED;
        }

在CreateEmitter发射器的onNext方法,首先调用isDisposed方法判断有没有中断订阅,如果没有才让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);
            }
        }

这就是RxJava中取消订阅事件的原理了

下一篇:RxJava 2.x 源码分析(二) 线程切换原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值