每天记录学习的新知识 : Disposable和CompositeDisposable

一、Disposable

1、简介

rxjava虽然好用,但是总所周知,容易遭层内存泄漏。也就说在订阅了事件后没有及时取阅,导致在activity或者fragment销毁后仍然占用着内存,无法释放。而disposable便是这个订阅事件,可以用来取消订阅。

2、调用

2.1、主动解除订阅
dispose():

注:切断观察者 与 被观察者 之间的连接,不会影响正在执行的Observer部分代码的调用

2.2、查询是否解除订阅 true 代表 已经解除订阅
isDisposed():
2.3、栗子

Disposable disposable;


                Observable.timer(100, TimeUnit.MILLISECONDS, Schedulers.io())
                        .observeOn(Schedulers.io()).subscribe(new Observer<Long>() {


                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable = d;
                    }

                    @Override
                    public void onNext(Long aLong) {
                        LogUtils.i(TAG, "write ... again");
                        write();
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }

//取消时
disposable.dispose();
2.4、取消订阅的操作,有必要在链路中使用吗?

其实还是有必要的,但是需要根据需求来。

比如,我需要在 void onNext(Long aLong) 方法中做一些操作,如果上面下发的数据满足条件,我就注销链路。

那么需要在 onComplete() 和 onError(Throwable e)方法中调用吗? 无需,因为他们已经调用了。

ObservableCreate中:

        @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()) {
                try {
                    observer.onError(t);
                } finally {
                    dispose();
                }
                return true;
            }
            return false;
        }

        @Override
        public void onComplete() {
            if (!isDisposed()) {
                try {
                    observer.onComplete();
                } finally {
                    dispose();
                }
            }
        }
2.5、关于内存泄漏

调用dipose确实可以终止数据流,但是不等于没有内存泄露。
查看 ObservableCreate 的源码可知,dispose只是简单地设置了 DISPOSED 状态,Observe 中关联的上下游对象并没有释放。所以当订阅了静态的 Observable 时,无法避免内存泄漏。

但是当订阅一个 Subject 时,dispose 确实可以有效释放对象,避免内存泄漏:

public void dispose() {
    if (super.tryDispose()) {
        parent.remove(this); //对象删除
    }
}

转自 详解 RxJava 的 Disposable:https://developer.aliyun.com/article/940680

2.6、关于 dispose 的实时性

前面分析知道,对于终端操作符 create、subscribe 等,其 Observer 在 dispose 时会标记当前状态为 DISPOSED。但对于其他操作符的 dispose 只是递归向上调用 parent 的 dispose 而已,并没有 DISPOSED 状态的设置,也就不会拦截发射中的数据。

调用dispose后,RxJava数据流不一定会立即停止,大部分操作符在调用 dispose 后,数据依然会发射给下游
关于 dispose 的实时性测试,下文可供参考

https://medium.com/stepstone-tech/the-curious-case-of-rxjava-disposables-e64ff8a06879

转自 详解 RxJava 的 Disposable:https://developer.aliyun.com/article/940680

二、CompositeDisposable

1、简介

一个disposable的容器,可以容纳多个disposable,添加和去除的复杂度为O(1)。

作用:管理订阅事件disposable。

注意:如果这个CompositeDisposable容器已经是处于dispose的状态,那么所有加进来的disposable都会被自动切断。

2、调用

在这里插入图片描述

2.1、实例化

compositeDisposable = new CompositeDisposable();

2.2、将disposable添加到容器中

CompositeDisposable.add()

如果容器已经 调用过 void dispose()方法,就不再接受新的添加

2.3、将disposable从容器中删除

CompositeDisposable.delete(disposable);

一般不直接调用,这个方法只是删除 CompositeDisposable 中,

OpenHashSet resources; 中存的 disposable 数据,不会进行 disposable.dispose

2.4、取消所有订阅

compositeDisposable.clear();

调用此方法,后续还可以继续向 CompositeDisposable 中添加数据: compositeDisposable.add()

2.5、取消disposable并从容器移除

使用 remove 方法,remove可以从 OpenHashSet resources; 内部容器把数据移除,然后再取消订阅,注意的是如果移除失败是不会进行取消的,要注意此方法只适用了disposable加入到compositeDisposable中

    @Override
    public boolean remove(@NonNull Disposable disposable) {
        if (delete(disposable)) {
            disposable.dispose();
            return true;
        }
        return false;
    }
2.6、取消所有订阅,并不再接收新订阅

compositeDisposable.dispose 会取消所有订阅,并不接收新订阅,这点区别于remove

    @Override
    public void dispose() {
        if (disposed) {
            return;
        }
        OpenHashSet<Disposable> set;
        synchronized (this) {
            if (disposed) {
                return;
            }
            disposed = true;
            set = resources;
            resources = null;
        }

        dispose(set);
    }

三、举例封装

1、针对像网络请求的功能模块,网络请求集体取消后续的需求进行封装

public class RxJavaGcManager {

    private static RxJavaGcManager instance;

    private RxJavaGcManager() {
    }

    public static RxJavaGcManager getInstance() {
        if (instance == null) {
            instance = new RxJavaGcManager();
        }
        return instance;
    }


    private CompositeDisposable compositeDisposable;

    public void add(Disposable disposable) {
        if (compositeDisposable == null) {
            compositeDisposable
                    = new CompositeDisposable();
        }
        compositeDisposable.add(disposable);
    }

    public void clearDisposable() {
        if (compositeDisposable != null) {
            compositeDisposable.clear();
        }
    }


调用:

RxJavaGcManager的clearDisposable方法取消所有订阅

2、一般场景的使用

如页面业务逻辑的订阅,我认为自己创建自己的管理类,比较容易管理

当然也可以使用Map管理CompositeDisposable 的形式对应个业务页面

public class RxRecycleUtil {

    private CompositeDisposable compositeDisposable;

    public RxRecycleUtil() {
        compositeDisposable = new CompositeDisposable();
    }

    /**
     * 加入 compositeDisposable 管理
     *
     * @param disposable -
     */
    public void add(Disposable disposable) {
        if (disposable != null) {
            compositeDisposable.add(disposable);
        }
    }

    /**
     * 已经加入 compositeDisposable 中的 disposable 如此取消
     *
     * @param disposable -
     */
    private boolean remove(Disposable disposable) {
        if (compositeDisposable != null) {
            return compositeDisposable.remove(disposable);
        } else {
            return false;
        }
    }

    /**
     * 取消所有
     */
    public void clear() {
        if (compositeDisposable != null) {
            compositeDisposable.clear();
            compositeDisposable = null;
        }
    }

    /**
     * 没有 加入 compositeDisposable 中的 disposable 如此取消
     *
     * @param disposable -
     */
    public void disposable(Disposable disposable) {
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }


}

参考地址

CompositeDisposable:https://blog.csdn.net/weixin_43724742/article/details/102991355

详解 RxJava 的 Disposable:https://developer.aliyun.com/article/940680

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周周都刷火焰猫头鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值