【RxJava】- RxLifecycle解決RxJava內(nèi)存泄露源碼分析

目錄

【RxJava】- 創(chuàng)建操作符源碼分析
【RxJava】- 變換操作符源碼分析
【RxJava】- 過(guò)濾操作符源碼分析
【RxJava】- 結(jié)合操作符源碼分析
【RxJava】- 連接操作符源碼分析

簡(jiǎn)介

在Activity中使用RxJava的時(shí)候诚撵,由于回調(diào)拌倍,RxJava持有Activity引用。當(dāng)Activity銷毀時(shí)舆逃,RxJava中的耗時(shí)任務(wù)還沒有完成米者,如果這時(shí)候沒有收到調(diào)用對(duì)應(yīng)的dispose()方法汉矿,那么RxJava中持有的資源得不到釋放,從而引起Activity的內(nèi)存泄露。如果在Activity中手動(dòng)調(diào)用动猬,這樣麻煩又不優(yōu)雅,所以這時(shí)候可以使用RxLifecycle來(lái)解決表箭。

使用

具體使用可以參考RxLifecycle赁咙,下面注意講解RxLifecycle源碼,帶你一步步了解RxLifecycle實(shí)現(xiàn)的真相免钻。

流程

分析之前彼水,先用RxJava創(chuàng)建一個(gè)觀察者模型任務(wù)。

Observable.create(emitter -> {}).compose(bindToLifecycle()).subscribe();

這里只分析bindToLifecycle()方法中的內(nèi)容极舔,其它都是RxJava中的操作符凤覆。

跟蹤到

public static <T> LifecycleTransformer<T> bindActivity(@NonNull Observable<ActivityEvent> lifecycle) {
    return RxLifecycle.bind(lifecycle, ACTIVITY_LIFECYCLE);
}
  • ACTIVITY_LIFECYCLE:Function實(shí)例,對(duì)Activity生命周期時(shí)間做映射拆魏。
  • lifecycle:是新創(chuàng)建的BehaviorSubject實(shí)例盯桦。

下一步

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

takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents)方法構(gòu)建一個(gè)新的Observable實(shí)例,即ObservableFilter對(duì)象渤刃∮德停·

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

參數(shù)lifecycle.share()

public final Observable<T> share() {return publish().refCount();}
public Observable<T> refCount() {
    return RxJavaPlugins.onAssembly(new ObservableRefCount<T>(onRefCount()));
}
    private ConnectableObservable<T> onRefCount() {
        if (this instanceof ObservablePublishClassic) {
            return RxJavaPlugins.onAssembly(
                    new ObservablePublishAlt<T>(((ObservablePublishClassic<T>)this).publishSource())
                   );
        }
        return this;
    }

最后調(diào)用bind(@Nonnull final Observable<R> lifecycle)返回一個(gè)持有上面創(chuàng)建的Observable實(shí)例的LifecycleTransformer對(duì)象。

  • subscribe()
    訂閱

發(fā)射Activity生命周期事件

發(fā)射Activity生命周期事件卖子,封裝RxLifecycle中的RxAppCompatActivity類里面(我繼承的是RxAppCompatActivity)略号。比如onCreate:

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.lifecycleSubject.onNext(ActivityEvent.CREATE);
}

onNext方法

public void onNext(T t) {
    ...
    Object o = NotificationLite.next(t);
    setCurrent(o);
    for (BehaviorDisposable<T> bs : subscribers.get()) {
        bs.emitNext(o, index);
    }
}

subscribers中的值是一個(gè)BehaviorDisposable數(shù)組,在subscribeActual方法中進(jìn)行添加洋闽。

protected void subscribeActual(Observer<? super T> observer) {
    BehaviorDisposable<T> bs = new BehaviorDisposable<T>(observer, this);
    if (add(bs)) {...};
    ...
}

emitNext方法中調(diào)用 test(value)來(lái)發(fā)射數(shù)據(jù)玄柠,如果已經(jīng)有數(shù)據(jù)處于發(fā)射中,者將數(shù)據(jù)保存起來(lái)诫舅,然后返回羽利。

public boolean test(Object o) {
    return cancelled || NotificationLite.accept(o, downstream);
}
public static <T> boolean accept(Object o, Observer<? super T> observer) {
    if (o == COMPLETE) {
        observer.onComplete();
        return true;
    } elseif (o instanceof ErrorNotification) {
        observer.onError(((ErrorNotification)o).e);
        return true;
    }
    observer.onNext((T)o);
    return false;
}

調(diào)用

Observable.create(emitter -> {}).compose(bindToLifecycle()).subscribe();
  • .subscribe()
    執(zhí)行.compose中返回實(shí)例的subscribeActual(Observer<? super T> observer)方法,observer是.subscribe()傳入的訂閱實(shí)例骚勘,即觀察者铐伴。

  • .compose(bindToLifecycle())

    bindToLifecycle()返回的是LifecycleTransformer實(shí)例∏味铮看一下compose(bindToLifecycle())實(shí)現(xiàn)当宴。

    public final <R> Observable<R> compose(ObservableTransformer<? super T, ? extends R> composer) {
    return wrap(((ObservableTransformer<T, R>) ObjectHelper.requireNonNull(composer, "composer is null")).apply(this));
    }
    
    public static <T> Observable<T> wrap(ObservableSource<T> source) {
      ObjectHelper.requireNonNull(source, "source is null");
      if (source instanceof Observable) {
          return RxJavaPlugins.onAssembly((Observable<T>)source);
      }
      return RxJavaPlugins.onAssembly(new ObservableFromUnsafeSource<T>(source));
    }
    

    首先調(diào)用LifecycleTransformer的apply方法,傳入被觀察者對(duì)象泽疆,即.create返回的實(shí)例户矢。
    apply方法做了什么

    public ObservableSource<T> apply(Observable<T> upstream) {
       return upstream.takeUntil(observable);
    }
    

    對(duì)被觀察者使用takeUntil操作符,傳入值為takeUntilCorrespondingEvent返回的ObservableFilter實(shí)例殉疼,新創(chuàng)建一個(gè)ObservableTakeUntil實(shí)例并返回梯浪。

    由于ObservableTakeUntil是Observable的子類捌年,所以.compose返回ObservableTakeUntil對(duì)象。

  • ObservableTakeUntil
    接下來(lái)就執(zhí)行到ObservableTakeUntil中的subscribeActual(Observer<? super T> child)方法挂洛。

    ObservableTakeUntil中的兩個(gè)參數(shù):

    • other
      takeUntilCorrespondingEvent返回的ObservableFilter實(shí)例
    • source
      被觀察者礼预,即.create返回的實(shí)例。
    public void subscribeActual(Observer<? super T> child) {
      TakeUntilMainObserver<T, U> parent = new TakeUntilMainObserver<T, U>(child);
      child.onSubscribe(parent);
      other.subscribe(parent.otherObserver);
      source.subscribe(parent);
    }
    

    child是觀察者實(shí)例虏劲,即.subscribe()中的訂閱者托酸。

    調(diào)用觀察者的onSubscribe方法,傳入持有觀察者實(shí)例TakeUntilMainObserver實(shí)例柒巫。

    調(diào)用ObservableFilter的subscribe方法励堡,調(diào)用被觀察者(即.create返回的實(shí)例)中的subscribe方法。前者傳入OtherObserver實(shí)例堡掏,后者傳入TakeUntilMainObserver實(shí)例应结。

    看一下takeUntilCorrespondingEvent方法:

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

    這里面的邏輯什么觸發(fā)呢,當(dāng)在Activity生命周期發(fā)射事件時(shí)泉唁,也就是上面講的RxAppCompatActivity生命周期發(fā)射事件鹅龄。

    .filter返回的是ObservableFilter對(duì)象。而ObservableFilter中的downstream是ObservableTakeUntil中的OtherObserver實(shí)例游两±悖看一下ObservableFilter中的onNext方法。

    public void onNext(T t) {
      if (sourceMode == NONE) {
          boolean b;
          try {
              b = filter.test(t);
          } catch (Throwable e) {
              fail(e);
              return;
          }
          if (b) {
              downstream.onNext(t);
          }
      } else {
          downstream.onNext(null);
      }
    }
    

    boolean b = filter.test(t)是使用combineLatest操作符返回的值贱案,規(guī)則是肛炮,當(dāng)需要觀察的生命周期事件(即ifecycle.take(1))和在Activity中發(fā)射的生命周期事件相等時(shí)返回true,否則返回false宝踪。

    比如觀察的是onStop生命周期侨糟,那么觀察的事件就是ActivityEvent.STOP,當(dāng)Activity調(diào)用onStop時(shí)瘩燥,那么filter.test(t)返回true秕重。

    downstream.onNext(t)調(diào)用ObservableTakeUntil中的onNext方法。

    public void onNext(U t) {
        DisposableHelper.dispose(this);
        otherComplete();
    }
    

    這里基本上就是去清理RxJava的相關(guān)數(shù)據(jù)了厉膀。其它情況類似溶耘。

  • bindUntilEvent(@NonNull ActivityEvent event)
    指定觀察那個(gè)生命周期事件。

其它

// If you want pre-written support preference Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.1.0'
// If you want to use Android Lifecycle for providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'

這兩個(gè)是在其它情況下事情 服鹅,具體自己看庫(kù)里面的代碼凳兵,很少。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末企软,一起剝皮案震驚了整個(gè)濱河市庐扫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖形庭,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铅辞,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡萨醒,警方通過(guò)查閱死者的電腦和手機(jī)斟珊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)验靡,“玉大人倍宾,你說(shuō)我怎么就攤上這事∈どぃ” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵钩乍,是天一觀的道長(zhǎng)辞州。 經(jīng)常有香客問(wèn)我,道長(zhǎng)寥粹,這世上最難降的妖魔是什么变过? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮涝涤,結(jié)果婚禮上媚狰,老公的妹妹穿的比我還像新娘。我一直安慰自己阔拳,他們只是感情好崭孤,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糊肠,像睡著了一般辨宠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上货裹,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天嗤形,我揣著相機(jī)與錄音,去河邊找鬼弧圆。 笑死赋兵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搔预。 我是一名探鬼主播霹期,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斯撮!你這毒婦竟也來(lái)了经伙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帕膜,沒想到半個(gè)月后枣氧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡垮刹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年达吞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荒典。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酪劫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寺董,到底是詐尸還是另有隱情覆糟,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布遮咖,位于F島的核電站滩字,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏御吞。R本人自食惡果不足惜麦箍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陶珠。 院中可真熱鬧挟裂,春花似錦、人聲如沸揍诽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寝姿。三九已至交排,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饵筑,已是汗流浹背埃篓。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留根资,地道東北人架专。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像玄帕,于是被迫代替她去往敵國(guó)和親部脚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容