一、介紹
RxLifecycle目的:解決RxJava使用中的內存泄漏問題。
例如,當使用RxJava訂閱并執(zhí)行耗時任務后,當Activity被finish時,如果耗時任務還未完成,沒有及時取消訂閱,就會導致Activity無法被回收,從而引發(fā)內存泄漏。
為了解決這個問題,就產生了RxLifecycle,讓RxJava變得有生命周期感知,使得其能及時取消訂閱,避免出現內存泄漏問題。
二、使用
首先來介紹下RxLifecycle的使用。
1.添加依賴
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
2.繼承容器類
Activity/Fragment需要繼承RxAppCompatActivity/RxFragment,主要支持如下幾種容器類:

只需要在項目中針對base類的容器中繼承實現對應的
Rx類即可,這一步主要是對生命周期的回調事件進行監(jiān)聽。
3.綁定容器生命周期
以Activity為例,主要有如下兩種方法:
bindUntilEvent(@NonNull ActivityEvent event)
bindToLifecycle()
針對Fragment也有同樣的兩種方法,只是方法名會有所不同。
下面詳細介紹這兩種方法的區(qū)別:
bindUntilEvent
該方法指定在哪個生命周期方法調用時取消訂閱。
其中ActivityEvent是一個枚舉類,對應于Activity的生命周期。
public enum ActivityEvent {
CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY
}
具體使用示例:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose {
Log.i(TAG, "Unsubscribing subscription from onDestory()")
}
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe {
Log.i(TAG, "Started in onCreate(), running until in onDestroy(): $it")
}
}
指定在生命周期onDestory()時,取消訂閱。
bindToLifecycle
在某個生命周期進行綁定,在對應的生命周期進行訂閱解除。
具體使用示例:
override fun onResume() {
super.onResume()
Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose {
Log.i(TAG, "Unsubscribing subscription from onPause()")
}
.compose(bindToLifecycle())
.subscribe {
Log.i(TAG, "Started in onResume(), running until in onPause(): $it")
}
}
在onResume()進行綁定訂閱,則在onPause()進行解除訂閱,生命周期是兩兩對應的。
三、原理解析
1.compose
首先來了解一下compose操作符。
compose(bindToLifecycle())
compose(bindUntilEvent(ActivityEvent.DESTROY))
如上所示,兩種綁定生命周期的方式,都是通過compose操作符進行實現的。
compose一般情況下可以配合Transformer使用,以實現將一種類型的Observable轉換成另一種類型的Observable,保證調用的鏈式結構。
那么接下來看該操作符在RxLifecycle中的應用,從bindToLifecycle和bindUntilEvent入手。
2.BehaviorSubject
public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
@Override
@CallSuper
protected void onResume() {
super.onResume();
lifecycleSubject.onNext(ActivityEvent.RESUME);
}
@Override
@CallSuper
protected void onPause() {
lifecycleSubject.onNext(ActivityEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
protected void onStop() {
lifecycleSubject.onNext(ActivityEvent.STOP);
super.onStop();
}
@Override
@CallSuper
protected void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}
RxAppCompatActivity中有一個關鍵對象BehaviorSubject
BehaviorSubject會發(fā)送離訂閱最近的上一個值,沒有上一個值的時候會發(fā)送默認值。如下圖:

所以lifecycleSubject會根據綁定訂閱的時期,不斷發(fā)送接下來的生命周期事件ActivityEvent。
3.LifecycleTransformer
接下來繼續(xù)看源碼,bindToLifecycle和bindUntilEvent都返回了一個LifecycleTransformer對象,那么LifecycleTransformer到底有什么用?
@ParametersAreNonnullByDefault
public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
FlowableTransformer<T, T>,
SingleTransformer<T, T>,
MaybeTransformer<T, T>,
CompletableTransformer
{
final Observable<?> observable;
LifecycleTransformer(Observable<?> observable) {
checkNotNull(observable, "observable == null");
this.observable = observable;
}
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.takeUntil(observable);
}
@Override
public Publisher<T> apply(Flowable<T> upstream) {
return upstream.takeUntil(observable.toFlowable(BackpressureStrategy.LATEST));
}
@Override
public SingleSource<T> apply(Single<T> upstream) {
return upstream.takeUntil(observable.firstOrError());
}
@Override
public MaybeSource<T> apply(Maybe<T> upstream) {
return upstream.takeUntil(observable.firstElement());
}
@Override
public CompletableSource apply(Completable upstream) {
return Completable.ambArray(upstream, observable.flatMapCompletable(Functions.CANCEL_COMPLETABLE));
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
LifecycleTransformer<?> that = (LifecycleTransformer<?>) o;
return observable.equals(that.observable);
}
@Override
public int hashCode() {
return observable.hashCode();
}
@Override
public String toString() {
return "LifecycleTransformer{" +
"observable=" + observable +
'}';
}
}
LifecycleTransformer實現了各種Transformer接口,能夠將一個 Observable/Flowable/Single/Completable/Maybe 對象轉換成另一個 Observable/Flowable/Single/Completable/Maybe對象。正好配合上文的compose操作符,使用在鏈式調用中。
4.takeUntil
接下來到了關鍵了,LifecycleTransformer到底把原來的Observable對象轉換成了什么樣子?
這就需要了解takeUntil操作符了!

當第二個
Observable發(fā)射了一項數據或者終止時,丟棄原Observable發(fā)射的任何數據。所謂的第二個Observable,即傳入takeUntil中的Observable對象。
理解了該操作符的作用,那么你可能就明白了,RxLifecycle就是通過監(jiān)聽第二個Observable發(fā)射的數據,來解除訂閱。
那么這第二個Observable是誰?
不就是在創(chuàng)建LifecycleTransformer的時候傳入構造函數中的嘛,那就來尋找一下什么時候創(chuàng)建的該對象即可。
從頭開始捋一捋:
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
該方法返回了LifecycleTransformer對象,繼續(xù)向下追溯。
public static <T, R> LifecycleTransformer<T> bindUntilEvent(@Nonnull final Observable<R> lifecycle,
@Nonnull final R event) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(event, "event == null");
return bind(takeUntilEvent(lifecycle, event));
}
private static <R> Observable<R> takeUntilEvent(final Observable<R> lifecycle, final R event) {
return lifecycle.filter(new Predicate<R>() {
@Override
public boolean test(R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(event);
}
});
}
繼續(xù)追蹤,馬上接近真相。
public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
return new LifecycleTransformer<>(lifecycle);
}
在該方法中創(chuàng)建了該對象,并傳入了一個Observable對象,通過上面方法即可知道該對象就是BehaviorSubject對象。
那么該對象在什么時候發(fā)送第一次數據呢?
這就要看上面的takeUntilEvent方法了。
關鍵在這一句lifecycleEvent.equals(event),只有當BehaviorSubject發(fā)送的ActivityEvent的值等于解除綁定的生命周期時,才會發(fā)送第一次數據。那么當發(fā)送第一次數據時,根據上面的分析就會解除訂閱的綁定。
那么針對bindToLifecycle方法,是進行怎樣的操作,使得在對應的生命周期進行解除訂閱呢?
還是繼續(xù)看源碼。
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
public static <T> LifecycleTransformer<T> bindActivity(@NonNull final Observable<ActivityEvent> lifecycle) {
return bind(lifecycle, ACTIVITY_LIFECYCLE);
}
其中ACTIVITY_LIFECYCLE為:
private static final Function<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE =
new Function<ActivityEvent, ActivityEvent>() {
@Override
public ActivityEvent apply(ActivityEvent lastEvent) throws Exception {
switch (lastEvent) {
case CREATE:
return ActivityEvent.DESTROY;
case START:
return ActivityEvent.STOP;
case RESUME:
return ActivityEvent.PAUSE;
case PAUSE:
return ActivityEvent.STOP;
case STOP:
return ActivityEvent.DESTROY;
case DESTROY:
throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
該函數的功能是會根據傳入的生命周期事件,返回對應的生命周期,如CREATE→DESTROY??磥硗ㄟ^該函數就可以實現在對應生命周期解綁了。
不過還需要一系列操作符的協(xié)助,繼續(xù)看源碼。
public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle,
@Nonnull final Function<R, R> correspondingEvents) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(correspondingEvents, "correspondingEvents == null");
return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
}
private static <R> Observable<Boolean> takeUntilCorrespondingEvent(final Observable<R> lifecycle,
final Function<R, R> correspondingEvents) {
return Observable.combineLatest(
lifecycle.take(1).map(correspondingEvents),
lifecycle.skip(1),
new BiFunction<R, R, Boolean>() {
@Override
public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(bindUntilEvent);
}
})
.onErrorReturn(Functions.RESUME_FUNCTION)
.filter(Functions.SHOULD_COMPLETE);
}
詳細看一下takeUntilCorrespondingEvent方法。
5.take
首先看一下take操作符,很簡單。
take(int)用一個整數n作為一個參數,只發(fā)射前面的n項,如下圖:

那么對應lifecycle.take(1).map(correspondingEvents),即獲取發(fā)送的第一個生命周期事件,再通過上面對應的函數,轉換為響應的生命周期。如果在onCreate中進行綁定,那么第一個發(fā)送的就是CREATE,返回的就是對應的DESTORY。
6.skip
skip(int)忽略Observable發(fā)射的前n項數據

lifecycle.skip(1),如果在onCreate中進行綁定,那么剩余的就是START,RESUME,PAUSE,STOP,DESTROY
7. combineLatest
最后還需要一個關鍵的操作符combineLatest,來完成對應生命周期的解除訂閱。
combineLatest操作符可以將2~9個Observable發(fā)射的數據組裝起來然后再發(fā)射出來。不過還有兩個前提:
- 所有的Observable都發(fā)射過數據。
- 滿足上面條件的時候任何一個
Observable發(fā)射一個數據,就將所有Observable最新發(fā)射的數據按照提供的函數組裝起來發(fā)射出去。
具體示例,如下圖所示:

按照第三個參數的函數,將lifecycle.take(1).map(correspondingEvents)和lifecycle.skip(1),進行combine
new BiFunction<R, R, Boolean>() {
@Override
public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(bindUntilEvent);
}
}
那么結果是
false,false,false,false,true
之后的onErrorReturn和filter是對異常的處理和判斷是否應該結束訂閱:
//異常處理
static final Function<Throwable, Boolean> RESUME_FUNCTION = new Function<Throwable, Boolean>() {
@Override
public Boolean apply(Throwable throwable) throws Exception {
if (throwable instanceof OutsideLifecycleException) {
return true;
}
//noinspection ThrowableResultOfMethodCallIgnored
Exceptions.propagate(throwable);
return false;
}
};
//是否應該取消訂閱,依賴于上游的boolean
static final Predicate<Boolean> SHOULD_COMPLETE = new Predicate<Boolean>() {
@Override
public boolean test(Boolean shouldComplete) throws Exception {
return shouldComplete;
}
};
所以,按照上面的例子,如果在onCreate()方法中進行綁定,那么在onDestory()方法中就會對應的解除訂閱。
四、總結
通過上面的分析,可以了解RxLifecycle的使用以及原理。
學習RxLifecycle的過程中,更加體會到了對于觀察者模式的使用,以及RxJava操作符的強大,各種操作符幫我們實現一些列的轉換。