rxJava源码解析系列五之Disposable

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

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

  Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("hello");
                emitter.onNext("world");
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    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

看一下运行运行结果

 可以看到,只要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<Disposable> 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<? super T> observer) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(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.
     *
     * <p>
     * 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的数据流的传递过程。

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RxJava中的flatMap操作符是一个非常常用的操作符,它可以将一个Observable发射的事件序列转换成多个Observables,然后将这些Observables发射的事件序列合并后再发射出去。 下面是flatMap操作符的源码解析: ```java public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) { ObjectHelper.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap<>(this, mapper, false, Integer.MAX_VALUE, bufferSize())); } ``` 可以看到,flatMap操作符的实现是通过创建一个ObservableFlatMap对象来完成的。其中,mapper参数表示将原始Observable发射的事件转换成的新Observable,它是一个Function类型的参数,即接受一个T类型的参数并返回一个ObservableSource类型的结果。 ObservableFlatMap的构造函数如下所示: ```java ObservableFlatMap(ObservableSource<T> source, Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { this.source = source; this.mapper = mapper; this.delayErrors = delayErrors; this.maxConcurrency = maxConcurrency; this.bufferSize = bufferSize; } ``` ObservableFlatMap的核心实现是在subscribeActual方法中完成的: ```java @Override public void subscribeActual(Observer<? super R> observer) { if (ObservableScalarXMap.tryScalarXMapSubscribe(source, observer, mapper)) { return; } source.subscribe(new FlatMapObserver<>(observer, mapper, delayErrors, maxConcurrency, bufferSize)); } ``` 在subscribeActual方法中,首先判断源Observable是否可以直接转换为ObservableScalarXMap,如果可以的话直接进行转换,否则创建一个FlatMapObserver对象并进行订阅。 FlatMapObserver是flatMap的核心实现类,它实现了Observer接口,并且在接收到源Observable发射的事件时,会先将事件转换成新的Observable,然后将新Observable的发射事件序列合并到一个新的Observable中,最后再将新的Observable发射出去。 ```java static final class FlatMapObserver<T, R> extends AtomicInteger implements Observer<T>, Disposable { // ... @Override public void onNext(T t) { ObservableSource<? extends R> o; try { o = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource"); } catch (Throwable e) { Exceptions.throwIfFatal(e); upstream.dispose(); onError(e); return; } if (cancelled) { return; } if (maxConcurrency != Integer.MAX_VALUE) { synchronized (this) { if (wip == maxConcurrency) { queue.offer(t); return; } wip++; } } o.subscribe(new InnerObserver(inner, delayErrors, this)); } // ... } ``` 在FlatMapObserver的onNext方法中,首先调用mapper将源Observable发射的事件转换成新的Observable,并进行非空检查。然后判断当前的并发度是否达到了最大值,如果达到了最大值,就将源Observable发射的事件放到队列中。否则,就将并发度加1,并订阅新Observable。 InnerObserver是FlatMapObserver的内部类,它实现了Observer接口,并在接收到来自新Observable的发射事件序列时,将它们合并到一个新的Observable中,并将新的Observable发射出去。 ```java static final class InnerObserver<R> implements Observer<R> { // ... @Override public void onNext(R t) { if (done) { return; } inner.onNext(t); } // ... } ``` 当所有的新Observable都完成后,FlatMapObserver会调用onComplete方法通知观察者。如果发生了异常,FlatMapObserver会调用onError方法通知观察者。同时,FlatMapObserver还实现了Disposable接口,可以通过dispose方法取消订阅。 综上所述,flatMap操作符的实现是比较复杂的,它通过创建ObservableFlatMap对象,并在subscribeActual方法中创建FlatMapObserver对象来完成转换操作。在FlatMapObserver中,它还需要实现对新Observable的订阅以及将新Observable发射的事件合并到一个新的Observable中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值