本菜鸡对于Rxjava的感觉就是,简便但上手难理解,熟练使用后越用越舒服。RXJava其实也用了很久了,但是之前一直没有系统学习过,都是伴随着OKGO来进行网络请求而已,在其他的地方并没有特别使用它,这段时间工作暂时没安排,趁此机会赶紧系统的学习一波。今天先记录记录一下,Rxjava2内存泄漏的问题。
首先我对RXJAVA内存泄漏的理解是,在线程和事件调度时,耗时任务在Activity/Fragment销毁时还没结束,并且Activity/Fragment销毁时又没有去处理,就会导致此Activity/Fragment无法被销毁 从而泄漏内存。
废话不多说,上栗子
private var sec=60L
//在TestAty中使用Rxjava开启一个耗时操作
Observable.intervalRange(0,sec,1,1,TimeUnit.SECONDS)
.map(object :Function<Long,Long>{
override fun apply(t: Long): Long {
return sec-t
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object :SimplerObserver2<Long>(this,true){
override fun onNext(t: Long) {
"${t}".logIt()
}
})
然后让我们不断的start这个Aty然后再finish的搞他
下面贴几张图来记录内存的变化
首先看一下App启动初始的内存占用(菜鸡直接在项目里面开的测试Activity所以初始化内存不小)
可以看到稳定之后内存大概就在75MB左右,下面贴一张操作之后的图
这都不用看栈实例了,很明显侧漏了一堆内存,已经爆到130MB的内存了。为了方便下面对比,我们还是看一下栈内实例。
可以看到栈内一堆TestAty
那么怎么解决呢,我网上查了一下,很多都是说的是RxLifecycle这个东西去控制,但是这东西需要你基类去继承,这对于强迫症来说简直就是噩耗。相比之下我更推荐AutoDispose这个东西。
上面两个都是需要额外依赖三方库。感觉好像很复杂,但是我试了一下,通过
CompositeDisposable.dispose()
此方法来一样能起到防止内存侧漏的问题,下面贴代码
private var compositeDisable: CompositeDisposable?=null
private fun intervRange(){
Observable.intervalRange(0,sec,1,1,TimeUnit.SECONDS)
.map(object :Function<Long,Long>{
override fun apply(t: Long): Long {
return sec-t
}
})
.observeOn(AndroidSchedulers.mainThread())
//SimplerObserver2是封装的一个观察者
.subscribe(object :SimplerObserver2<Long>(this,true){
override fun onNext(t: Long) {
"${t}".logIt()
}
})
}
SimplerObserver2代码如下
abstract class SimplerObserver2<T>(private val c:Context,private val isLoading:Boolean):Observer<T> {
override fun onError(e: Throwable) {
}
override fun onComplete() {
if (c is TestAty){
c.loadingDialog.dismiss()
}
}
//关键代码,在OnSubscrib时将disposable添加当Activity中的CompositeDisposable
override fun onSubscribe(d: Disposable) {
if (c is TestAty){
c.loadingDialog.show()
c.addDisable(d)
}
}
}
最后在Activity的ondestory()时
compositeDisable.dispose()
这样就能取消activity的订阅,下面我们再重复操作一下刚刚的操作看看效果如何
创建销毁次数大概是刚刚的两倍,内存消耗也从75MB涨到了85MB,看上去好像也泄漏了,那么看一下栈内实例
没有TestAty的实例了,说明已经被销毁了,也就是说TestAty没有再内存泄漏了。大家使用的话上面的CompositeDisposable和Add的方法可以写在BaseAty中,方便使用
好了至此Rxjava内存泄漏的问题我觉得是解决了,但是反复操作后从75MB到了85MB,这是什么原因有大佬知道吗。以上可以说是笔记,仅供参康,有不对的大佬发现了请指出。
网友评论