RxJava2 (二)取消订阅流程 dispose( ) 源码阅读

当前版本 2.2.19
RxJava2 (一)订阅流程源码阅读
RxJava2 (二)取消订阅流程 dispose( ) 源码阅读
RxJava2 (三)线程切换源码阅读
RxJava2 (四)切换UI主线程源码阅读
RxJava2 (五)just操作符源码阅读
RxJava2 (六)map操作符源码阅读

代码示例
// 创建被观察者
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
    @Override
    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
        emitter.onNext("Hello World");
        emitter.onComplete();
    }
});
// 订阅观察者
observable.subscribe(new Observer<String>() {
    @Override
    public void onSubscribe(Disposable d) {
        System.out.println("onSubscribe");
        // 取消订阅后,ObservableEmitter发出的消息,观察者Observer将不会再收到.
        d.dispose();
    }
    @Override
    public void onNext(String s) {
        System.out.println("onNext: " + s);
    }
    @Override
    public void onError(Throwable e) {
        System.out.println("onError");
    }
    @Override
    public void onComplete() {
        System.out.println("onComplete");
    }
}
Observer.onSubscribe(Disposable)
  • 调用observable.subscribe(Observer)方法后最终会调用ObservableCreate.subscribeActual()方法, 在该方法中会调用观察者的onSubscribe(Disposable),详细的解释可以看上一篇文章
d.dispose(); 取消订阅

对象dDisposable类型, Disposable是一个接口,具体实现需要看它的子类CreateEmitter

// ObservableCreate.CreateEmitter类
public final class ObservableCreate<T> extends Observable<T> {
    static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {
        // 取消订阅
        @Override
        public void dispose() {
            // this代表当前CreateEmitter对象,往下看.
            DisposableHelper.dispose(this);
        }
        // 判断是否取消订阅
        @Override
        public boolean isDisposed() {
            return DisposableHelper.isDisposed(get());
        }
    }
}
// DisposableHelper类
public enum DisposableHelper implements Disposable {
    DISPOSED
    ;
    // field为上一步传入的CreateEmitter对象,CreateEmitter继承了AtomicReference<Disposable>.
    // AtomicReference<Disposable>知识可以看这两个博客:
    // https://www.jianshu.com/p/84c75074fa03
    // https://blog.csdn.net/zxc123e/article/details/52057289

    public static boolean dispose(AtomicReference<Disposable> field) {
        // 获取AtomicReference<Disposable>对象中的值,不过CreateEmitter对象是直接new出来的,
        // 所以它的父类AtomicReference<Disposable>中并不存在Disposable这个值.此时current是为null.
        Disposable current = field.get();
        // DISPOSED是一个枚举,类型为DisposableHelper.
        Disposable d = DISPOSED;
        if (current != d) {
            // 此时current为null,肯定与d不相等.
            // getAndSet(d): 为field对象value设置为DisposableHelper.DISPOSED对象,并且返回旧值,旧值上面说过为null.
            // 至此,field对象也就是上一步的CreateEmitter对象中value字段此时的值为DisposableHelper.DISPOSED对象.
            current = field.getAndSet(d);
            if (current != d) {
                if (current != null) {
                    current.dispose();
                }
                return true;
            }
        }
        return false;
    }
    // 判断CreateEmitter对象中value变量和当前枚举类相等.
    // 如果相等,代表订阅已经取消了
    // 如果不相等,代表订阅没有取消
    public static boolean isDisposed(Disposable d) {
        return d == DISPOSED;
    }
}

通过分析,取消观察者与被观察者间的订阅关系,向CreateEmitter对象中的value字段赋值DisposableHelper.DISPOSED对象就行了.

emitter.onNext("Hello World")

发射数据,最终会调用到CreateEmitter中的onNext(T t)方法,这个过程会判断订阅是否取消.下面来看下.

public final class ObservableCreate<T> extends Observable<T> {
    static final class CreateEmitter<T> extends AtomicReference<Disposable> implements ObservableEmitter<T>, Disposable {
        @Override
        public void onNext(T t) {
            ...
            if (!isDisposed()) {
                observer.onNext(t);
            }
        }
        // 判断是否取消订阅
        @Override
        public boolean isDisposed() {
            // 如果CreateEmitter对象调用了dispose()方法,最终会向CreateEmitter对象中存入DisposableHelper.DISPOSED对象.
            // CreateEmitter.get():就是获取当前CreateEmitter对象中value变量的值,也就是枚举对象.
            // 上面有分析过
            // 传入的枚举对象如果和枚举类中的枚举对象地址值相同,代表订阅已经取消了
            // 如果地址值不相同,代表订阅没有取消
            return DisposableHelper.isDisposed(get());
        }
    }
}
CompositeDisposable

简单说下CompositeDisposable,它可以管理RxJava2批量取消订阅操作.

CompositeDisposable mCompositeDisposable = new CompositeDisposable();
// 将所有的disposable对象都由mCompositeDisposable对象保管.
mCompositeDisposable.add(disposable);

下面看下CompositeDisposable对象的add()

// CompositeDisposable类
public final class CompositeDisposable implements Disposable, DisposableContainer {
    volatile boolean disposed; // 这个标记位是用来标记当前的CompositeDisposable对象是否已经执行了取消订阅的操作
    @Override
    public boolean add(@NonNull Disposable disposable) {
        ObjectHelper.requireNonNull(disposable, "disposable is null");
        if (!disposed) { // 假如当前CompositeDisposable对象还未执行取消操作
            synchronized (this) {
                if (!disposed) {// 假如当前CompositeDisposable对象还未执行取消操作
                    OpenHashSet<Disposable> set = resources; 
                    if (set == null) {
                        // 创建Set集合
                        set = new OpenHashSet<Disposable>();
                        resources = set;
                    }
                    // 将disposable对象存入集合中
                    set.add(disposable);
                    return true;
                }
            }
        }
        // 假如当前的CompositeDisposable对象已经执行过了取消订阅的操作,那么就对传入的disposable进行取消操作
        disposable.dispose();
        return false;
    }
    // 对CompositeDisposable对象中set集合中的所有disposable进行取消订阅的操作
    @Override
    public void dispose() {
        if (disposed) {
            return;
        }
        OpenHashSet<Disposable> set;
        synchronized (this) {
            if (disposed) {
                return;
            }
            disposed = true; // 将标记置为true,表示CompositeDisposable对象执行过了取消订阅的操作.
            set = resources;
            resources = null;
        }
        dispose(set);
    }
    
    void dispose(OpenHashSet<Disposable> set) {
        if (set == null) {
            return;
        }
        List<Throwable> errors = null;
        Object[] array = set.keys();
        for (Object o : array) {
            if (o instanceof Disposable) {
                try {
                    // 这里就是实际执行取消订阅的地方.
                    ((Disposable) o).dispose();
                }...
            }
        }
        ...
    }
}

CompositeDisposable对象主要用来批量取消订阅,比如Activity中有多个RxJava2订阅,我想在Activity销毁的时候统一对这些订阅进行取消,那么就可以先将Disposable对象都添加到CompositeDisposable对象中,等到Activity执行onDestroy生命周期的时候调用CompositeDisposable.dispose(),进行统一取消订阅操作.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值