RxLifecycle原理分析

RxLifecycle源碼地址

RxLifecycle有兩種使用方法:
1、bindToLifecycle直接綁定生命周期

  Observable.interval(1, TimeUnit.SECONDS)
            .doOnDispose(new Action() {
                @Override
                public void run() throws Exception {
                    Log.i(TAG, "Unsubscribing subscription from onStart()");
                }
            })
            .compose(this.<Long>bindToLifecycle())//使用bindToLifecycle
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long num) throws Exception {
                    Log.i(TAG, "Started in onStart(), running until in onStop(): " + num);
                }
            });

2再姑、bindUntilEvent綁定特定的ActivityEvent

Observable.interval(1, TimeUnit.SECONDS)
            .doOnDispose(new Action() {
                @Override
                public void run() throws Exception {
                    Log.i(TAG, "Unsubscribing subscription from onCreate()");
                }
            })
            .compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE))//使用bindUntilEvent
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long num) throws Exception {
                    Log.i(TAG, "Started in onCreate(), running until onPause(): " + num);
                }
            });

原理其實(shí)一樣胳岂,只分析bindToLifecycle是怎么綁定Activity的生命周期的编整。
首先bindToLifecycle是通過compose操作的,compose比較常見乳丰,比如切換線程的時(shí)候掌测,用compose操作符讓代碼更好看些,compose操作的是個(gè)Transformer产园,跟進(jìn)去看,bindToLifecycle果然返回一個(gè)封裝了的LifecycleTransformer:

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);
}

好汞斧,這里出現(xiàn)了兩個(gè)重要的東西lifecycleSubject和ACTIVITY_LIFECYCLE夜郁,bind方法將這兩個(gè)東西處理后,返回的LifecycleTransformer粘勒。lifecycleSubject和ACTIVITY_LIFECYCLE是什么竞端?看源碼:

private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

lifecycleSubject原來是個(gè)BehaviorSubject,BehaviorSubject可以當(dāng)做Observable來發(fā)射消息庙睡,查看RxActivity或RxAppCompatActivity類的生命周期回調(diào)方法,lifecycleSubject都發(fā)送了該生命周期標(biāo)識乘陪,比如:

protected void onPause() {
    lifecycleSubject.onNext(ActivityEvent.PAUSE);
    super.onPause();
}
protected void onStop() {
    lifecycleSubject.onNext(ActivityEvent.STOP);
    super.onStop();
}
protected void onDestroy() {
    lifecycleSubject.onNext(ActivityEvent.DESTROY);
    super.onDestroy();
}

我們來想下统台,一般情況下我們都是希望在Activiy退出(onDestroy)后,取消訂閱消息啡邑,那么 lifecycleSubject.onNext(ActivityEvent.DESTROY)在onDestroy中發(fā)射后饺谬,就要通知該取消訂閱消息了,正好takeUntil操作符可以滿足要求谣拣,takeUntil操作符簡要說明如下:

//Observable1發(fā)射數(shù)據(jù)募寨,但是當(dāng)Observable2也發(fā)射數(shù)據(jù)時(shí),訂閱就取消了森缠。
Observable1
 .takeUntil(Observable2)
 .subscribe(new Consumer);

我們想要的正是在ActivityEvent.DESTROY消息發(fā)送后拔鹰,訂閱取消」蠛回到上面列肢,我們知道了lifecycleSubject是干什么用的了,lifecycleSubject就是發(fā)射生命周期標(biāo)識宾茂,通過這個(gè)來監(jiān)控Activity生命周期瓷马。
那ACTIVITY_LIFECYCLE是干什么用的?ACTIVITY_LIFECYCLE是個(gè)Function:

  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");
                }
            }
        };

這個(gè)Function的作用就是返回訂閱消息所對應(yīng)的生命周期跨晴,意思是如果你在onCreate訂閱欧聘,那么就返回DESTROY,意味只有在Activity onDestroy的時(shí)候取消訂閱端盆。以下分析都依在DESTROY中取消訂閱為例怀骤。
lifecycleSubject和ACTIVITY_LIFECYCLE作用明白了,繼續(xù)往下走,bind方法里面是:

 public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle, @Nonnull final Function<R, R> correspondingEvents) {
        return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
    }

輸入的lifecycleSubject和ACTIVITY_LIFECYCLE被takeUntilCorrespondingEvent處理了焕妙,這個(gè)方法才是RxLifecycle最精華的地方:

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);
    }

拆開看:

//這兩個(gè)其實(shí)就是lifecycleSubject蒋伦,可以理解為兩個(gè)Observable
lifecycle.take(1).map(correspondingEvents),//map操作符調(diào)用correspondingEvents(就是上面的ACTIVITY_LIFECYCLE)的作用上面說了,類似輸入CREATE焚鹊,輸出DESTROY
lifecycle.skip(1),//跳過之前發(fā)射的生命周期痕届,比如在onStart里發(fā)射,跳過去,只操作onStart之后的生命周期

combineLatest操作符的作用就是操作這兩個(gè)Observable(其實(shí)都是lifecycleSubject)研叫,再回到takeUntil操作符势决,只有在onDestroy的時(shí)候發(fā)射,才能取消訂閱蓝撇,而在其他生命周期,比如onPause陈莽,onStop這些不能取消渤昌,這時(shí)候我們有了第一個(gè)數(shù)據(jù)源lifecycle.take(1).map(correspondingEvents)返回的DESTROY,還有第二個(gè)數(shù)據(jù)源lifecycle.skip(1)返回的PAUSE走搁,STOP独柑,DESTROY這些訂閱后的生命周期,那么就可以操作:只有第二個(gè)數(shù)據(jù)等于第一個(gè)數(shù)據(jù)才會取消訂閱私植,于是回到源碼,通過combineLatest的第三個(gè)參數(shù)來完成這個(gè)比較:

new BiFunction<R, R, Boolean>() {
     @Override
     public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception{
          return lifecycleEvent.equals(bindUntilEvent);//兩個(gè)數(shù)據(jù)源比較
      }
 })

好了忌栅,到了這一步,我們得到了每個(gè)生命周期回調(diào)時(shí)曲稼,takeUntil操作符操作的Observable索绪,類型是Boolean,只有DESTROY時(shí)返回true贫悄,其他生命周期來時(shí)返回false瑞驱。但是false不能返回啊,因?yàn)閠akeUntil一旦把false發(fā)射出去窄坦,那訂閱就取消了唤反,我們只想在true的時(shí)候才發(fā)射出去,filter操作符上場了:

Observable\\前面已經(jīng)得到的false或true,通過filter鸭津,只有true才發(fā)射
.filter(Functions.SHOULD_COMPLETE);

static final Predicate<Boolean> SHOULD_COMPLETE = new Predicate<Boolean>() {
        @Override
        public boolean test(Boolean shouldComplete) throws Exception {
            return shouldComplete;
        }
};

SHOULD_COMPLETE很簡單彤侍,輸入輸出一樣,但是完成了只有true才發(fā)射的要求逆趋。
至此盏阶,RxLifecycle通過bindToLifecycle綁定生命周期的原理應(yīng)該清楚了,再總結(jié)下:
1、在Activiy的每個(gè)生命周期回調(diào)里通過lifecycleSubject發(fā)射當(dāng)前生命周期標(biāo)識,比如發(fā)射A
2闻书、通過ACTIVITY_LIFECYCLE得到想要取消訂閱的生命周期標(biāo)識B
3般哼、在takeUntilCorrespondingEvent方法里比較A和B,得到是否相等的結(jié)果C
4惠窄、通過filter操作符只發(fā)射3中結(jié)果是true的C
5蒸眠、因?yàn)槭褂昧藅akeUntil操作符,一旦4里發(fā)射了杆融,那訂閱就取消了楞卡。

最后takeUntil是在哪里調(diào)用的呢,回到開始的LifecycleTransformer:

public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
                                                      FlowableTransformer<T, T>,
                                                      SingleTransformer<T, T>,
                                                      MaybeTransformer<T, T>,
                                                      CompletableTransformer
{
 @Override
    public ObservableSource<T> apply(Observable<T> upstream) {
        return upstream.takeUntil(observable);
    }
    .........
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒋腮,隨后出現(xiàn)的幾起案子淘捡,更是在濱河造成了極大的恐慌,老刑警劉巖池摧,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焦除,死亡現(xiàn)場離奇詭異,居然都是意外死亡作彤,警方通過查閱死者的電腦和手機(jī)膘魄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竭讳,“玉大人创葡,你說我怎么就攤上這事【盥” “怎么了灿渴?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長胰舆。 經(jīng)常有香客問我骚露,道長,這世上最難降的妖魔是什么缚窿? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任荸百,我火速辦了婚禮,結(jié)果婚禮上滨攻,老公的妹妹穿的比我還像新娘够话。我一直安慰自己,他們只是感情好光绕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布女嘲。 她就那樣靜靜地躺著,像睡著了一般诞帐。 火紅的嫁衣襯著肌膚如雪欣尼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天停蕉,我揣著相機(jī)與錄音愕鼓,去河邊找鬼。 笑死慧起,一個(gè)胖子當(dāng)著我的面吹牛菇晃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚓挤,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼磺送,長吁一口氣:“原來是場噩夢啊……” “哼驻子!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起估灿,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤崇呵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后馅袁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體域慷,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年汗销,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犹褒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡大溜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出估脆,到底是詐尸還是另有隱情钦奋,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布疙赠,位于F島的核電站付材,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏圃阳。R本人自食惡果不足惜厌衔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捍岳。 院中可真熱鬧富寿,春花似錦、人聲如沸锣夹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽银萍。三九已至变勇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贴唇,已是汗流浹背搀绣。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戳气,地道東北人链患。 一個(gè)月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像瓶您,于是被迫代替她去往敵國和親锣险。 傳聞我的和親對象是個(gè)殘疾皇子蹄皱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345