0.前言
使用Rxjava的人越來越多厘唾,rxjava現(xiàn)在已經(jīng)更新到rxjava3了巾钉,因其簡潔效率高的特點備受程序猿喜愛。然而由rxjava處理不但引起的內(nèi)存泄漏問題也不得不讓人頭疼,每次使用完都要手動取消掉訂閱也很麻煩而且不一定執(zhí)行滔驶。為了解決這個問題,由此誕生了rxlifecycle卿闹,使用rxlifecycle可以跟蹤lifeOwnner的生命周期從而自動取消訂閱揭糕,但是卻有許多限制和問題,詳情見 為什么不使用 RxLifecycle?,作者已經(jīng)在文章里面說了锻霎。文章最后還親自推薦使用AutoDisposable著角,連他本人都認為rxlifecycle不如AutoDisposable了。網(wǎng)上關于AutoDisposable和LiveData相關使用的文章有很多旋恼,但是卻找不到LiveData結合AutoDisposable一起使用的文章吏口,著實讓人費解。很明顯冰更,liveData使得代碼僅僅在Activity處于活動狀態(tài)下執(zhí)行产徊,如果代碼使用了Rxjava訂閱處理數(shù)據(jù)(在網(wǎng)略請求中很常見,網(wǎng)略請求經(jīng)常使用Retrofit+okhttp+Rxjava蜀细,詳情見筆者另一篇文章 使用Kotlin+Rretrofit+rxjava+設計模式+MVP封裝網(wǎng)絡請求),這個時候如果不及時取消訂閱囚痴,則會引起內(nèi)存泄漏
1.導入
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
// alternatively, just ViewModel
implementation "android.arch.lifecycle:viewmodel:1.1.1"
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.1"
//autodispose
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.0.0-RC2'
implementation 'com.uber.autodispose:autodispose:1.0.0-RC2'
2.使用
這里舉個栗子:
- ViewModel
package foolish
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModel
import beans.response.TaskBean
import com.uber.autodispose.AutoDispose
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
import comment.LogUit
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.observers.DisposableObserver
import io.reactivex.schedulers.Schedulers
//TestModel作為MVP或MVVM中的Present,專門負責處理數(shù)據(jù)
class TestModel:ViewModel(){
val taskLiveData= MutableLiveData<Observable<TaskBean>>()//ViewModel內(nèi)部持有LiveData
fun initData( lifecycleOwner: LifecycleOwner){
//此處選擇在TestModel內(nèi)部處理LiveData(網(wǎng)上教程很多是把LiveData放在View中處理)
taskLiveData.observe(lifecycleOwner,object : Observer<Observable<TaskBean>>{
override fun onChanged(observable: Observable<TaskBean>?) {
observable!!.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner)))//使用AutoDispose綁定lifecycleOwner审葬,自動取消訂閱
.subscribe(object : DisposableObserver<TaskBean>() {
override fun onComplete() {
}
override fun onNext(t: TaskBean) {
LogUit.printI("TaskPresentPrint", "t=${t.toString()}")
}
override fun onError(e: Throwable) {
//處理網(wǎng)略錯誤
}
})
}
})
}
}
//網(wǎng)略請求獲取數(shù)據(jù)
fun requestTaskDetail(taskDetailToBean: TaskDetailToBean){
LogUit.printI(TAG,"獲取詳情:json="+ Gson().toJson(taskDetailToBean))
HTTPProxy.instance!!.execute( this,taskDetailToBean, Constant.REQUEST_TASK_DETAIL);
}
如注釋所言深滚,只要在訂閱時使用
`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner)))
就可以綁定lifecycleOwner奕谭,從而跟隨生命周期自動取消訂閱
這樣,只要在網(wǎng)略請求回調(diào)時(這里給出栗子):
//網(wǎng)略請求回調(diào)
override fun <T> onResponse(observable: Observable<T>, typeLogin: Int) {
try {
//業(yè)務請求類型
when (typeLogin) {
//獲取任務請求
Constant.REQUEST_TASK -> taskLiveData.postValue(observable as (Observable<TaskBean>))
//獲取任務詳情請求
Constant.REQUEST_TASK_DETAIL ->taskDetailLiveData.postValue(observable as (Observable<TaskDetailBean>))
}
} catch (e :Exception){
e.printStackTrace();
}
}
調(diào)用taskLiveData.postValue(observable as (Observable<TaskBean>))
更新數(shù)據(jù)即可痴荐,taskLiveData只會在Activity處于活動狀態(tài)下處理(常見網(wǎng)略請求回調(diào)后更新UI血柳,此時如果UI所在的Activity已消亡就會引發(fā)錯誤),在liveData里面處理網(wǎng)略請求回調(diào)的數(shù)據(jù)就不會造成資源浪費生兆,然后又在Activity消亡時自動取消訂閱难捌,就不會引發(fā)內(nèi)存泄漏
- View中使用
val testModel by lazy { ViewModelProviders.of(this).get(TestNodel::class.java) }//綁定lifeCycleOwner,獲取ViewModel
...
testModel.initData(this)
testModel.requestTaskDetail(taskDetailToBean)
這里省略去部分代碼鸦难,總之根吁,在網(wǎng)略請求之后,會調(diào)用自定義的一個接口合蔽,回調(diào)上面給出的onResponse方法击敌,然后更新liveData的數(shù)據(jù)。網(wǎng)略請求使用的是一個rxjava+retrofit+okhttp自己封裝的工具拴事,代碼就不給出了沃斤。
- 測試
網(wǎng)上有段很內(nèi)存泄漏的代碼,很好測試內(nèi)存泄漏刃宵,這里給出來以供測試時復制粘貼
Observable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : io.reactivex.Observer<Long>{
override fun onComplete() {
LogUit.printI(RegisterOrLoginModel.TAG,"onComplete")
}
override fun onSubscribe(d: Disposable) {
LogUit.printI(RegisterOrLoginModel.TAG,"onSubscribe:d=$d")
}
override fun onNext(t: Long) {
LogUit.printI(RegisterOrLoginModel.TAG,"onNext:t=$t,")
}
override fun onError(e: Throwable) {
LogUit.printI(RegisterOrLoginModel.TAG,"onError=${e.message}")
}
})
測試的方法是這樣的:定義兩個Activity:A和B衡瓶,從A跳轉(zhuǎn)到B,B持有栗子中的TestViewModel牲证,然后在taskLiveData.observe(```)方法的處理中添加這段代碼哮针,每個一秒就會打印log一次,然后按返回鍵回到A坦袍,停止Log打印诚撵,如果不加上
`as`(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner)))
則會一直打印log,發(fā)生內(nèi)存泄漏键闺。
3.注意
AutoDispose的版本已經(jīng)更新到1.3.0了,如果使用超過1.0.0的版本(目前只測試到這個版本)澈驼,綁定lifecycleOwner時就會要求使用androidx里面的lifecycleOwner辛燥,這將與LiveData的1.1.0版本沖突(筆者只試了下這個版本),因為LiveData要求的lifecycleOwner是android.arch.lifecycle.LifecycleOwner的缝其,筆者尚未找到可以同時滿足這兩個條件的Activity(其實是沒去找哈哈)
另外挎塌,本文代碼使用kotlin寫,還在使用java的要去更新一下技能了内边,使用kotlin不用擔心以前的java代碼不能使用榴都,因為從java轉(zhuǎn)換成kotlin非常容易!D洹嘴高!
原創(chuàng)文章