rxJava和rxAndroid源码解析系列五之Disposable

这个系列的前几篇文章是传统rxjava的数据流传递模式,我们知道,observable的链式调用,是下游被观察者持有上有被观察者的过程,发起订阅的时候是上游观察者持有下游观察者的过程。到最先的被观察者,通过本层级实现的消息队列或者发射器开始发射数据流,而上游的观察者或消息队列持有下游的观察者,通过观察者的接Observer实现最终回调。以上是对以上几篇文章的总结,不明白的朋友可以详细看一下这个系列的前几篇文章。既然明白了rxjava的数据流传递机制,试想一下,假如因为某些原因,我不想等待回调的结果了,为了节省内存,我要把发射关掉(比如在activity或fragment下面,用rxjava做耗时操作,而我想隐藏或关闭该界面,为了避免内存泄漏,必须终止rxjava的传递过程,该怎么办呢?),这也是本篇文章主要探讨Disposable,为什么这个东东可以终止呢,还是从源码开始吧,这才符合本博客的主题嘛!

首先,我们先看一下直观的现象,就用以下代码为例。

  Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext("hello");
                emitter.onNext("world");
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    Disposable disposable;
                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable=d;
                    }
                    @Override
                    public void onNext(String s) {
                        disposable.dispose();
                        Log.i("test",s);
                    }
                    @Override
                    public void onError(Throwable e) {

                    }
                    @Override
                    public void onComplete() {

                    }
                });

                                                   代码片段1

看一下运行运行结果

rxJava和rxAndroid源码解析系列五之Disposable_第1张图片

 可以看到,只要disposable调用dispose方法,这个发射机制就终结了。

现象已经看到了,我们通过源代码解析上面的现象。

先贴一张对象关系图,

这个关系图,是根据代码调用关系画出来的。 当我们在测试代码里面调用disposable.dispose()的时候,这个disposable是ObserveOnObserver的实例,所以它的方法如下

  @Override
        public void dispose() {
            if (!disposed) {//只要你的代码没有问题,不发生异常,初始值为false
                disposed = true;//已经被处理过
                upstream.dispose();//关闭上游的数据源
                worker.dispose();//关闭worker
                if (getAndIncrement() == 0) {
                    queue.clear();//队列清空
                }
            }
        }

                                                代码片段2

一般情况下,disposed为false,然后往下执行。upstream是SubscribeOnObserver它的实例,那么这个类实现了Disposable接口,那它又做了什么呢?请看代码

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

                                           代码片段3

这个DisposableHelper.dispose方法做了什么操作

 /**
     * Atomically disposes the Disposable in the field if not already disposed.
     * @param field the target field
     * @return true if the current thread managed to dispose the Disposable
     */
    public static boolean dispose(AtomicReference field) {
        Disposable current = field.get();
        Disposable d = DISPOSED;
        if (current != d) {
            current = field.getAndSet(d);//把当前field的Disposable取出来,并设置为已经处理过,
            if (current != d) {
                if (current != null) {
                    current.dispose();//处理掉dispose
                }
                return true;
            }
        }
        return false;
    }

                                           代码片段4

该方法就是AtomicReference里面的value取出来,判断一下是否处理了,如果没处理过,处理掉。处理了,返回false

我们再回到代码片段3,这里的upstream是CreateEmitter的实例,它存储的Disposable为null,根据代码片段四,给upstream设置Disposable为DISPOSED,设置这样,CreateEmitter就可以停止发射了嘛,看看一下方法就明白了

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

 

/**
     * Checks if the given Disposable is the common {@link #DISPOSED} enum value.
     * @param d the disposable to check
     * @return true if d is {@link #DISPOSED}
     */
    public static boolean isDisposed(Disposable d) {
        return d == DISPOSED;
    }

 根据以上方法,可以知道CreateEmitter的isDisposed()返回true,这会对发射数据产生影响嘛,答案是肯定的,看一下代码

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

 CreateEmitter的isDisposed()返回true,所以不会往下游发射数据。

 

那代码片段3的DisposableHelper.dispose(this);这个代码做了什么事呢?这个this还记得吧,是SubscribeOnObserver的实例。

DisposableHelper.dispose(this)方法里面的参数是atomicReference里面设置了一个Disposable,什么时候设置的呢?经过查找源码可以看到,是在ObservableSubscribeOn.subscribeActual方法里面设置的,这个value是什么呢?看下源码

@Override
    public void subscribeActual(final Observer observer) {
        final SubscribeOnObserver parent = new SubscribeOnObserver(observer);

        observer.onSubscribe(parent);
        //该行代码设置的disposable,scheduler.scheduleDirect方法创建了disposable
        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }

那我们点击进去看看,

/**
     * Schedules the execution of the given task with the given time delay.
     *
     * 

* This method is safe to be called from multiple threads but there are no * ordering guarantees between tasks. * * @param run the task to schedule * @param delay the delay amount, non-positive values indicate non-delayed scheduling * @param unit the unit of measure of the delay amount * @return the Disposable that let's one cancel this particular delayed task. * @since 2.0 */ @NonNull public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) { final Worker w = createWorker(); final Runnable decoratedRun = RxJavaPlugins.onSchedule(run); //这个是个disposable,w是它的属性,NewThreadWorker DisposeTask task = new DisposeTask(decoratedRun, w); //w这里面包装的是线程池 w.schedule(task, delay, unit); return task; }

DisposeTask也就是AtomicReference的value,那根据代码片段4会执行DisposeTask的dispose()方法,它是怎么调用的呢?

  @Override
        public void dispose() {
runner是不是当前线程,而且w是不是newThreadWorker
            if (runner == Thread.currentThread() && w instanceof NewThreadWorker) {
                ((NewThreadWorker)w).shutdown();关闭
            } else {
                w.dispose();
            }
        }

根据运行环境两者都可能发生,那么newThreadWorker这两个方法的实现是什么呢?

 @Override
    public void dispose() {
        if (!disposed) {
            disposed = true;
            executor.shutdownNow();
        }
    }

    /**
     * Shuts down the underlying executor in a non-interrupting fashion.
     */
    public void shutdown() {
        if (!disposed) {
            disposed = true;
            executor.shutdown();
        }
    }

关闭线程池,厉害了。如果还没有发生线程转换订阅,执行以上的操作 ,不会把任务添加到线程池,如果已经进行任务订阅,把上游的回调关闭,不会往下游发射事件。ok,代码片段3分析完毕,让我们再回到代码片段二的worker.dispose()这个代码

而这个worker是HandlerWorker的实例,而dispose的实现是什么呢?

   @Override
        public void dispose() {
            disposed = true;
//去除消息,不会发生线程转换的最终回调
            handler.removeCallbacksAndMessages(this /* token */);
        }

当然了,还有其他地方也进行了限制,在这里不做详细叙述,代码片段2的最后一段话就是清空队列,整个数据流的传递过程就终止了。也符合Observer的接口定义里面注释的那样

    /**
     * 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);

dispose方法可以在任何时候撤销连接,也就是rxjava的数据流的传递过程。

你可能感兴趣的:(android)