RxJava 的内存泄露问题
runRxLambda 和 runRxLambdaViewModel 只是个扩展函数,可以不用理会,下面两段代码唯一的区别就是第二段增加了 AndroidLifecycleScopeProvider.from(view),这也导致了第二段代码不会出现内存泄露,而第一段代码会出现内存泄露。
runRxLambda(Observable
.intervalRange(0,100,1,1,TimeUnit
.SECONDS
),{
Log
.e("222","runRxLambda-time:$it")
},{},{})
runRxLambdaViewModel(AndroidLifecycleScopeProvider
.from(view
),Observable
.intervalRange(0,100,1,1,TimeUnit
.SECONDS
),{
Log
.e("222","runRxLambdaViewModel-time:$it")
mElapsedRealTime
.postValue(it
)
})
下面的日志对应的操作流程是:跳转一个页面后点击一个按钮,执行上面的两段代码,然后立即返回上一个页面。
通过日志也可以看出第一段代码内存泄露了吧,页面都已经关闭但是相关的逻辑代码还在执行。这就是 RxJava使用中常见的内存泄露问题。
解决方案
在 onSubscribe(d: Disposable) 回调中保存 dispose ,在页面关闭的时候调用.dispose() 方法使用RxLifeCycle , 地址:https://github.com/trello/RxLifecycle使用AutoDispose , 地址:https://uber.github.io/AutoDispose/#overview
这里仅介绍AutoDispose2 的使用
AutoDispose2
引入依赖
implementation
'com.uber.autodispose2:autodispose-android:2.0.0'
implementation
'com.uber.autodispose2:autodispose-androidx-lifecycle:2.0.0'
AutoDispose 解决的问题:
AutoDispose是一种RxJava 2+工具,用于通过处置/取消将RxJava流的执行自动绑定到提供的作用域。通常(尤其是在移动应用程序中),Rx订阅需要停止以响应某些事件(例如,在Android应用程序中执行Activity#onStop()时)。为了支持RxJava 2中的这种常见情况,我们构建了AutoDispose。
在 Activity 和 Fragment 中使用
解决办法伪代码如下:
myObservable
.doStuff()
.as(autoDisposable(this)) // The magic
.subscribe(s -> ...);
只要这样一行as(autoDisposable(this)),您将按照作用域指示自动取消订阅myObservable , 这有助于防止在Observable发出项目时出现许多错误类别。
在 ViewModel 或者 Presenter 中使用
class MineViewModel(val view
:LifecycleOwner
) : BaseViewModel() {
private val mElapsedRealTime
= MutableLiveData
<Long>()
val countDownTime
: MutableLiveData
<Long> by lazy
{
mElapsedRealTime
}
fun
getTime(){
runRxLambdaViewModel(AndroidLifecycleScopeProvider
.from(view
),
Observable
.intervalRange(0,100,1,1,TimeUnit
.SECONDS
),{
mElapsedRealTime
.postValue(it
)
})
}
}
runRxLambdaViewModel 的代码没啥,主要是使用 kotlin 的扩展函数和高阶函数封装了RxJava线程切换的代码。
源码地址:https://github.com/YGragon/FrameDemo
参考
AutoDispose 官网Android架构中添加AutoDispose解决RxJava内存泄漏ViewModel 概览AutoDispose使用AutoDispose解决RxJava内存泄漏(Android)