? ? 隨著RxJava的熱火與普及,他的缺點(diǎn)也逐漸被大家所發(fā)現(xiàn)。特別是在開發(fā)者使用不注意的時(shí)候,極容易造成內(nèi)存泄漏。比如以下經(jīng)典場景:使用RxJava發(fā)布一個(gè)訂閱后,當(dāng)Activity被finish,此時(shí)訂閱邏輯還未完成,如果沒有及時(shí)取消訂閱,就會(huì)導(dǎo)致Activity無法被回收,從而引發(fā)內(nèi)存泄漏。當(dāng)然,也因此提出了好一些解決方案。其中有兩種方案被大家所認(rèn)可:
? ? 1、通過進(jìn)一步封裝,手動(dòng)在適當(dāng)時(shí)機(jī),取消訂閱;
? ? 2、監(jiān)聽所處活動(dòng)(Aty/Frag)的生命周期,在特定的生命周期階段進(jìn)行取消訂閱;
? ? 目前,本人所采取的是方案1,因?yàn)楸救瞬扇〉腗VP模式,活動(dòng)(Aty/Frag)主要進(jìn)行View層的操作,這個(gè)方案的優(yōu)點(diǎn)在于在原設(shè)計(jì)框架上,能夠相對(duì)獨(dú)立地在Presenter層進(jìn)行處理以及個(gè)別訂閱夠比較靈活地進(jìn)行訂閱取消處理。缺點(diǎn)就是,過于依賴于開發(fā)者本身的主觀意識(shí),需要在每一次都進(jìn)行手動(dòng)處理。也因此,對(duì)于RxLifecycle進(jìn)行了解,知道其采取的是方案2的原理,在了解過程中,看到好些大神在推薦AutoDispose,閱讀了好些博客,覺得需要對(duì)其進(jìn)行及時(shí)歸納,在此做一下筆記。
RxLifecycle基本
? ? 具體的使用步驟,可以到官方或者網(wǎng)上查看一下,有很多,在此簡單說明一下,不過多贅述。在引入相對(duì)應(yīng)的庫之后,需要在對(duì)應(yīng)的Aty/Frag(推薦在BaseAty/BaseFrag中)繼承其對(duì)應(yīng)的封裝的類。具體的操作步驟為:
????1、Activity/Fragment需繼承RxAppCompatActivity/RxFragment;
? ? 2、在訂閱者中,compose操作符綁定容器生命周期(有兩種方式,原理和操作地方都是一樣的):
? ? ? ? 2.1、使用bindToLifecycle()
? ? ? ? 2.2、使用bindUntilEvent()
? ? ? 如:// 當(dāng)執(zhí)行onDestory()時(shí), 自動(dòng)解除訂閱
????????Observable.interval(1, TimeUnit.SECONDS)
?????????.doOnDispose(newAction() {.... })? ? ? ? ? ? ? ? ? ?
?????????.compose(this.bindToLifecycle()) //方式2:.compose(this.bindUntilEvent(ActivityEvent.DESTROY))
?????????.subscribe(newConsumer() {...? });
? ? 原理解析
? ? ?上面我們說了,其最基礎(chǔ)的原理是通過監(jiān)聽活動(dòng)的生命周期,進(jìn)行對(duì)訂閱者的操作。那它的具體實(shí)現(xiàn)原理又是怎么樣的呢?我們先看看源碼的截圖:

? ? ? ? 上圖沒有完全截取完,是在對(duì)應(yīng)的周期回調(diào)方法內(nèi),進(jìn)行相似的操作,可參考o(jì)nStart與onResume方法體。我們可以看到,其里面主要是存儲(chǔ)了一個(gè)BehaviorSubject?對(duì)象,而BehaviorSubject?(釋放訂閱前最后一個(gè)數(shù)據(jù)和訂閱后接收到的所有數(shù)據(jù))其實(shí)本身也是一個(gè)發(fā)布者Observable。也就是在圖中我們看到的那樣,在對(duì)應(yīng)的生命回調(diào)方法中進(jìn)行對(duì)應(yīng)的ActivityEvent的發(fā)送。
? ? ? ? 從源碼上看,我們也可以知道,bindToLifecycle()方法實(shí)際返回了一個(gè)LifecycleTransformer,LifecycleTransformer的作用,根據(jù)個(gè)人理解是將上游數(shù)據(jù)源進(jìn)行攔截并對(duì)其進(jìn)行執(zhí)行takeUntil方法(有的博主說是實(shí)現(xiàn)了不同響應(yīng)式數(shù)據(jù)類(Observable、Flowable等)的Transformer接口)。
? ??takeUntil操作符
? ? 接下來就得看看takeUntil是干嘛用的了:當(dāng)?shù)诙€(gè)Observable發(fā)射了一項(xiàng)數(shù)據(jù)或者終止時(shí),丟棄原Observable發(fā)射的任何數(shù)據(jù)。到這里我們?cè)诳纯丛镜拇a:

? ? ? ? 可以看出,Activity.<Long>bindToLifecycle()實(shí)際上就是指定上游的數(shù)據(jù)源,當(dāng)接收到某個(gè)Observable(就是LifecycleTransformer中那個(gè)神秘的成員變量)的某個(gè)事件時(shí),該數(shù)據(jù)源自動(dòng)解除訂閱。
????到這里,我們就知道基本的流程了:當(dāng)我們將其進(jìn)行調(diào)用bindToLifecycle的時(shí)候,內(nèi)部的會(huì)對(duì)這條訂閱放入第二個(gè)發(fā)布者,而RxAppCompatActivity通過BehaviorSubject對(duì)象對(duì)應(yīng)的生命回調(diào)接口會(huì)進(jìn)行對(duì)應(yīng)的消息發(fā)布,其再通過LifecycleTransformer里進(jìn)行多種發(fā)布者的響應(yīng)數(shù)據(jù)類,調(diào)取takeUntil,當(dāng)?shù)诙€(gè)發(fā)布者發(fā)布信息的時(shí)候進(jìn)行訂閱解除。
? ? 進(jìn)一步探究
? ? 如果只為了基本原理流程,到這里就可以結(jié)束了,但是為了探究一下,內(nèi)部到底是怎么將第二個(gè)發(fā)布者放入這條訂閱里面呢?或者說,BehaviorSubject對(duì)象發(fā)布的消息是怎么去驅(qū)動(dòng)或者實(shí)現(xiàn)第二個(gè)發(fā)布者的操作呢?他們兩個(gè)是不是同一個(gè)人?
? ? 其實(shí)上文的BehaviorSubject對(duì)象就是我們所說的第二個(gè)發(fā)布者(也許在前頭的說辭會(huì)造成你們的誤解或者說明不清晰,我十分抱歉)。這也是前頭,我們一直強(qiáng)調(diào)的,他本身也是一個(gè)發(fā)布者的原因。讓我們看一下他里面重要的源碼之一:

? ? 1、lifecycle.take(1)指的是最近發(fā)射的事件,比如說我們?cè)趏nCreate()中執(zhí)行了bindToLifecycle,那么lifecycle.take(1)指的就是ActivityEvent.CREATE,經(jīng)過map(correspondingEvents),這個(gè)map中傳的函數(shù)就是 1中的ACTIVITY_LIFECYCLE:

? ??也就是說,lifecycle.take(1).map(correspondingEvents)實(shí)際上是返回了CREATE對(duì)應(yīng)的事件DESTROY,它意味著本次訂閱將在Activity的onDestory進(jìn)行取消。
? ? ? 2、lifecycle.skip(1)就簡單了,除去第一個(gè)保留剩下的,以ActivityEvent.Create為例,這里就剩下:
????????????ActivityEvent.START、ActivityEvent.RESUME、ActivityEvent.PAUSE、ActivityEvent.STOP、ActivityEvent.DESTROY
? ? ? 3、 第三個(gè)參數(shù) 意味著,lifecycle.take(1).map(correspondingEvents)的序列和 lifecycle.skip(1)進(jìn)行combine,形成一個(gè)新的序列:
????????????false,false,fasle,false,true
????????????這意味著,當(dāng)Activity走到onStart生命周期時(shí),為false,這次訂閱不會(huì)取消,直到onDestroy,為true,訂閱取消。
? ? ? ?4、而后的onErrorReturn和filter是對(duì)異常的處理和判斷是否應(yīng)該結(jié)束訂閱。
? ? 至此,我們?cè)倏偨Y(jié)一下整個(gè)RxLifecycle的原理流程:
? ??1.在Activity中,定義一個(gè)Observable(Subject),在不同的生命周期發(fā)射不同的事件;
????2.通過compose操作符(內(nèi)部實(shí)際上還是依賴takeUntil操作符),定義了上游數(shù)據(jù),當(dāng)其接收到Subject的特定事件時(shí),取消訂閱;
????3.Subject的特定事件并非是ActivityEvent,而是簡單的boolean,它已經(jīng)內(nèi)部通過combineLast操作符進(jìn)行了對(duì)應(yīng)的轉(zhuǎn)化。
? ? 以上內(nèi)容,多數(shù)來自參考博客,如有異議或者參考博客本人禁止,請(qǐng)與本人聯(lián)系!如有錯(cuò)誤或者偏頗方面,希望批評(píng)指正,不勝感激!
參考博文:
---------------------
作者:?卻把清梅嗅? 來源:CSDN? ?題目:Android官方架構(gòu)組件:Lifecycle詳解&原理分析
鏈接:https://blog.csdn.net/mq2553299/article/details/79029657
---------------------
作者:不詳? 來源:紅黑聯(lián)盟? ?題目:RxLifecycle的使用及源碼解讀