Android rxjava和LiveData中的内存泄漏

Posted 码农乐园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android rxjava和LiveData中的内存泄漏相关的知识,希望对你有一定的参考价值。

最近的一个项目,是采用由RxJava、LiveData提供支持的响应式架构。尽管这些库功能强大,内存泄漏的情况;

什么是内存泄漏

内存中不再使用的对象,被另一个正在使用的对象引用,导致 GC 无法清除它并释放内存

如果我们有两个相互持有强引用的对象,即使没有任何外部引用,也会发生内存泄漏。这就是所谓的保留周期。这在 android 上通常不是问题,因为 Java GC 使用的是标记和清除算法。

一,rxjava的内存泄漏

(1)存在内存泄漏问题

在使用rxjava的时候,如果没有及时解除订阅,在退出activity的时候,异步线程还在执行。对activity还存在引用,此时就会产生内存泄漏。

(2)常规手动取消订阅(不推荐)

为了防止内存泄漏的出现,我们需要在onDestroy取消订阅

Observable.interval(1000, TimeUnit.MILLISECONDS)
                    .subscribe(new Observer<Long>() 
                        @Override
                        public void onSubscribe(Disposable d) 
                            disposable = d;
                        

                        @Override
                        public void onNext(Long aLong) 

                        

                        @Override
                        public void onError(Throwable e) 

                        

                        @Override
                        public void onComplete() 

                        
                    );
@Override
protected void onDestroy() 

    if(disposable != null && !disposable.isDisposed())
        //取消订阅
        disposable.dispose();
    
    super.onDestroy();

以上代码的缺点很明显:

必须在onSubscribe中保存Disposable对象,然后在onDestroy方法里面取消订阅,如果有多个Observable时,很明显Disposable也会有多个,这样代码看起来紊乱,逻辑复杂,可读性差。

那么有没有什么办法对Disposable统一管理呢?

3)使用CompositeDisposable来管理Disposable

CompositeDisposable是一个存放Disposable的集合,它是一个容器,可以在BaseActivity里new一个CompositeDisposable对象,在BaseActivity的子类中可以使用该对象对Disposable统一管理。

CompositeDisposable也属于手动取消订阅,但显然比单独管理Disposable的方法强多了。

(4)RxLifecycle(自动取消订阅)(推荐)
Observable
      .interval(1000, TimeUnit.MILLISECONDS)
      .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))
      .subscribe(new Consumer<Long>() 
          @Override
          public void accept(Long aLong) throws Exception 
          Log.d("aaa", String.valueOf(aLong));
          
      );

RxLifecycle将Observable和Activity(Fragment)的生命周期绑定在一起,使用compose关键字来确定Observable将要在哪个生命周期执行时自动取消订阅

(5)AutoDispose(自动取消订阅)(推荐)

Observable
                    .interval(1000, TimeUnit.MILLISECONDS)
                    //AutoDispose的关键语句
                    .as(AutoDispose.<Long>autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                    .subscribe(new Consumer<Long>() 
                        @Override
                        public void accept(Long aLong) throws Exception 
                            Log.d("aaa", String.valueOf(aLong));
                        
                    );

AutoDispose要比RxLifecycle更加简单,有人说使用AutoDispose取代RxLifecycle也是有一定道理的,毕竟RxLifecycle需要继承对应的RxActivity、RxFragment,而AutoDispose却不用

二,LiveData可能产生的泄漏分析

订阅LiveData错误使用context

有一个RecyclerView通过. 渲染 a 的片段Adapter。您将如何观察项目列表并更新Adapter? 通常你会在你的订阅中拥有一个LiveData项目,然后使用.ViewModelDiffUtil

但是您会在哪里定义该订阅?有两种可能的选择:您可以在片段中创建订阅,然后将更新的项目列表发送到Adapter,或者您可以将您的传递ViewModel给Adapter并Adapter直接观察更改.

最后,LiveData 与 RxJava

虽然 LiveData 和 RxJava 都属于观察者模式的实现,但是他们的本质是完全不同的。

LiveData 只是数据的储存类,本身不支持复杂的线程操作和事件序列,也没有异常处理。与 RxJava 相比,具有体积小,学习成本低等优点。

RxJava 是一个完整的基于事件的观察序列,用来处理异步操作的框架。使用 RxJava 可以方便的切换线程,同时 RxJava 拥有的众多操作符也可以让逻辑变的清晰可循。配合 Retrofit 大大地简化了网络操作。但是学习曲线较陡,大部分人只会一些简单的操作。

以上是关于Android rxjava和LiveData中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

Android Jetpack架构组件一文带你了解LiveData(使用篇)

带有 RxJava Single 的 Android Livedata 在房间数据库中不起作用

使用 ViewModel、LiveData 和 RxJava 在 recyclerview 中处理数据和加载指示器的正确方法

Android Jetpack架构组件带你了解LiveData(原理篇)

android livedata进行顺序调用

对 Android 的 LiveData 网传的数据倒灌做一个深层次的解释