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 中处理数据和加载指示器的正确方法