RxAndroid之Rxlifecycle使用
随着Android第三库的普及,RxJava和RxAndroid(https://github.com/ReactiveX/RxAndroid)越来越被人熟知,简洁的语法,配合Java8Lambda表达式,使代码的结构更加清晰,通过线程调度器更容易控制和切换线程,种种优点,使用它的人也越来越多。但是使用不好,很容易导致内存泄露。Rxlifecycle(https://github.com/trello/RxLifecycle)就使被用来严格控制由于发布了一个订阅后,由于没有及时取消,导致Activity/Fragment无法销毁导致的内存泄露。
开源项目
RxLifecycle地址:https://github.com/trello/RxLifecycle。
该项目是为了防止RxJava中subscription导致内存泄漏而诞生的,核心思想是通过监听Activity、Fragment的生命周期,来自动断开subscription以防止内存泄漏。
Rxlifecycle使用非常方便简单,如下:
1.集成
build.gradle添加
//Rxlifecycle
compile''com.trello:rxlifecycle:0.3.1''
compile''com.trello:rxlifecycle-components:0.3.1''
//Rxjava
compile''io.reactivex:rxjava:1.0.16''
Components包中包含RxActivity、RxFragment等等,可以用Rxlifecycle提供的,也可以自定义。
2.Sample解析
官方sample源码:两种使用方法:
1.手动设置取消订阅的时机,例子1、例子3
2.绑定生命周期,自动取消订阅,例子2
publicclassMainActivityextendsRxAppCompatActivity{
//Note:Activity需要继承RxAppCompatActivity,fragment需要继承RxFragment,等等
//可以使用的组件在components包下面
privatestaticfinalStringTAG="RxLifecycle";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate()");
setContentView(R.layout.activity_main);
//SpecificallybindthisuntilonPause()
//Note:例子1:
Observable.interval(1,TimeUnit.SECONDS)
.doOnUnsubscribe(newAction0(){
@Override
publicvoidcall(){
Log.i(TAG,"UnsubscribingsubscriptionfromonCreate()");
}
})
//Note:手动设置在activityonPause的时候取消订阅
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(newAction1(){
@Override
publicvoidcall(Longnum){
Log.i(TAG,"StartedinonCreate(),runninguntilonPause():"+num);
}
});
}
@Override
protectedvoidonStart(){
super.onStart();
Log.d(TAG,"onStart()");
//Note:例子2:
//Usingautomaticunsubscription,thisshoulddeterminethatthecorrecttimeto
//unsubscribeisonStop(theoppositeofonStart).
Observable.interval(1,TimeUnit.SECONDS)
.doOnUnsubscribe(newAction0(){
@Override
publicvoidcall(){
Log.i(TAG,"UnsubscribingsubscriptionfromonStart()");
}
})
//Note:bindToLifecycle的自动取消订阅示例,因为是在onStart的时候调用,所以在onStop的时候自动取消订阅
.compose(this.bindToLifecycle())
.subscribe(newAction1(){
@Override
publicvoidcall(Longnum){
Log.i(TAG,"StartedinonStart(),runninguntilinonStop():"+num);
}
});
}
@Override
protectedvoidonResume(){
super.onResume();
Log.d(TAG,"onResume()");
//Note:例子3:
//`this.`isnecessaryifyou''recompilingonJDK7orbelow.
//Ifyou''reusingJDK8+,thenyoucansafelyremoveit.
Observable.interval(1,TimeUnit.SECONDS)
.doOnUnsuwww.baiyuewang.netbscribe(newAction0(){
@Override
publicvoidcall(){
Log.i(TAG,"UnsubscribingsubscriptionfromonResume()");
}
})
//Note:手动设置在activityonDestroy的时候取消订阅
.compose(this.bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(newAction1(){
@Override
publicvoidcall(Longnum){
Log.i(TAG,"StartedinonResume(),runninguntilinonDestroy():"+num);
}
});
}
...
如下代码:
Observable.just("helloworld!")
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.flatMap(newFunc1>(){
@Override
publicObservablecall(Strings){
returnObservable.interval(1,TimeUnit.SECONDS);
}
})
.subscribe(newAction1(){
@Override
publicvoidcall(LongaLong){
Log.i(TAG,"....oh,oh,no!!..........."+aLong);
}
});
activity生命周期paused的时候
Log.i(TAG,"....oh,oh,no!!..........."+aLong);
还会执行么??会会…
如果你想全部都不执行:
Observable.just("helloworld!")
.flatMap(newFunc1>(){
@Override
publicObservablecall(Strings){
returnObservable.interval(1,TimeUnit.SECONDS);
}
})
//fuck....here
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(newAction1(){
@Override
publicvoidcall(LongaLong){
Log.i(TAG,"....oh,oh,no!!..........."+aLong);
}
});
tip-2
Observable.interval(1,TimeUnit.SECONDS)
.doOnUnsubscribe(newAction0(){
@Override
publicvoidcall(){
Log.i(TAG,"Unsubscribingsubscription......");
}
})
.doOnNext(newAction1(){
@Override
publicvoidcall(LongaLong){
Log.i(TAG,"........fuck..........."+aLong);
}
})
.flatMap(newFunc1>(){
@Override
publicObservablecall(LongaLong){
returnObservable.just(aLong+"");
}
})
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(newAction1(){
@Override
publicvoidcall(Stringnum){
Log.i(TAG,"..........shit..........."+num);
}
});
activity在paused的时候,
Log.i(TAG,"........fuck..........."+aLong);
Log.i(TAG,"..........shit..........."+num);
都不会执行…而且会unsubscribe
延伸:
RxLifecycle-当Activity被destory时自动暂停网络请求
问题
Android开发中常会有这样一个场景:
发送网络请求->2.服务器处理请求并返回数据->3.client端接收数据,绘制UI。
在前两步一般都是不会出现问题的,但是在第三步,当数据返回给client端时,如果页面已经不在了,那么就无法去绘制UI,很有可能会导致意向不到的问题。因此,为了解决这个问题,一个好的思路就是当页面离开时,自动断开网络请求数据的处理过程,即数据返回后不再进行任何处理。
思考
要达到上面这样一个功能,我们可以思考,至少需要两部分:
随时监听Activity(Fragment)的生命周期并对外发射出去;
在我们的网络请求中,接收生命周期并进行判断,如果该生命周期是自己绑定的,如Destory,那么就断开数据向下传递的过程。
分析
可以看到,首先有一个核心功能要实现:就是既能够监听Activity生命周期事件并对外发射,又能够接收每一个生命周期事件并作出判断。为了实现这个功能,可以联想到RxJava中的Subject,既能够发射数据,又能够接收数据。
Subject介绍
了解Subject的读者可以跳过这部分。
如何理解Subject呢?
很容易,在RxJava里面,Observable是数据的发射者,它会对外发射数据,然后经过map、flatmap等等数据处理后,最终传递给Observer,这个数据接收者。因此,抛开中间数据处理不管,可以看出,Observable对外发射数据,是数据流的开端;Observer接收数据,是数据流的末端。
那么Subject呢?看一眼源码:
/
RepresentsanobjectthatisbothanObservableandanObserver.
/
publicabstractclassSubjectextendsObservableimplementsObserver{}
首先,它extendsObservable,说明Subject具备了对外发射数据的能力,即拥有了from()、just()等等;另外,它又implementsObserver,说明又能够处理数据,具备onNext()、onCompleted等等。
然后,Subject毕竟只是一个抽象类,那么我们要如何使用它呢?
这里介绍一种最简单的:PublishSubject:
PublishSubject |
|