Android架構(gòu)中添加AutoDispose解決RxJava內(nèi)存泄漏

概述

在我的上一篇文章 解決RxJava內(nèi)存泄漏(前篇):RxLifecycle詳解及原理分析 中,詳細(xì)闡述了

  • 如何通過使用 RxLifecycle 解決Android開發(fā)中RxJava的可能會(huì)導(dǎo)致的內(nèi)存泄漏問題;
  • RxLifecycle 內(nèi)部的實(shí)現(xiàn)原理;

在文章的最后,我提到了 AutoDispose 這個(gè)庫,這個(gè)庫同樣可以解決Android生命周期組件導(dǎo)致的RxJava的內(nèi)存泄漏情況。

但是不得不考慮的是,目前國內(nèi)的Android開發(fā)圈子中,RxLifecycle已經(jīng)逐漸為人所熟知,包括著名的一些開源架構(gòu)也都采用RxLifecycle替代手動(dòng)的處理方式 。比如 JessYanMVPArms

隨著越來越多的項(xiàng)目添加了RxLifecycle,我需要給出一個(gè)足夠有說服力的理由,足夠讓工程師同僚們?nèi)L試將AutoDispose替換RxLifecycle,或者讓他們在新的項(xiàng)目中優(yōu)先考慮使用AutoDispose。

我花了一些時(shí)間研究了AutoDispose源碼,并且在公司的新項(xiàng)目中嘗試使用AutoDispose,我嘗試將自己的所得分享出來,希望能夠拋磚引玉——如果看完之后,仍舊覺得 AutoDispose 的思想和設(shè)計(jì)沒什么用,至少也讓客官您斬掉這個(gè)念頭,繼續(xù)安穩(wěn)地使用 RxLifecycle 。

本文的主要內(nèi)容如下:

  • AutoDispose的基礎(chǔ)使用
  • AutoDispose的基本原理
  • AutoDispose和RxLifecycle的區(qū)別
  • 如何添加到目前的Android項(xiàng)目中(以MVP架構(gòu)為例)
  • 小結(jié)

基礎(chǔ)使用

官方文檔永遠(yuǎn)是最好的說明書:

AutoDispose: Automatic binding+disposal of RxJava 2 streams.

1、添加依賴

compile 'com.uber.autodispose:autodispose:x.y.z'
compile 'com.uber.autodispose:autodispose-android-archcomponents:x.y.z'

x.y.z請參照官網(wǎng)的最新版本,寫這篇文章時(shí),最新版本為0.6.1,即:

compile 'com.uber.autodispose:autodispose:0.6.1'
compile 'com.uber.autodispose:autodispose-android-archcomponents:0.6.1'

2、在你的代碼中直接使用,比如:

//在Activity中使用
myObservable
    .map(...)
    .subscribeOn(...)
    .observeOn(...)
    .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))  
    .subscribe(s -> ...);

通過給Observable(或者Single、Completable、Flowable等響應(yīng)式數(shù)據(jù)類型,本文皆以O(shè)bservable為例)添加這行代碼:

as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(lifecycleOwner))

該Observable就會(huì)在Activity的onDestory()生命周期時(shí),自動(dòng)解除訂閱,以防止因生命周期組件的生命周期而導(dǎo)致的RxJava內(nèi)存泄漏事件。

看到這里,對比RxLifecycle的代碼使用方式:

myObservable
    .compose(RxLifecycle.bind(lifecycle))
    .subscribe();

似乎都差不多,都是通過添加一行代碼實(shí)現(xiàn)RxJava事件流與組件生命周期的綁定,那么替換RxLifecycle的意義何在?

先按住這個(gè)問題不表,我先簡單闡述一下AutoDispose的原理。

基本原理

直接長篇大論針對源碼逐行分析,無疑是愚蠢的——我無法保證讀者能夠耐住性子看完枯燥無味的源碼分析,然后興致勃勃去嘗試這個(gè)庫,這與我初衷不符。

拋開細(xì)節(jié),直接闡述其設(shè)計(jì)思想。

首先前提是,您需要對Google最新的Lifecycle組件有一定的了解,在這里我列出之前寫的博客以供參考:

Android官方架構(gòu)組件:Lifecycle詳解&原理分析

同時(shí),如果您對RxLifecycle的原理也掌握的話,相信對于接下來的內(nèi)容,閱讀起來會(huì)更加輕松:

解決RxJava內(nèi)存泄漏(前篇):RxLifecycle詳解及原理分析

我們首先思考三個(gè)問題:

as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))

  • this是一個(gè)什么樣的參數(shù)?
  • 如何實(shí)現(xiàn)生命周期的綁定?
  • as方法執(zhí)行后生成了一個(gè)什么?

1、我傳了一個(gè)什么參數(shù)?

這個(gè)this直觀的講,就是Activity本身,當(dāng)然它也可以是Fragment,這個(gè)參數(shù)對象只有一個(gè)要求,就是必須實(shí)現(xiàn)LifecycleOwner接口。

LifecycleOwner接口是Google Android官方架構(gòu)組件:Lifecycle的一個(gè)重要組件,在v7包中,F(xiàn)ragmentActivity和Fragment都實(shí)現(xiàn)了這個(gè)接口,實(shí)現(xiàn)了這個(gè)接口的對象都擁有生命周期(Lifecycle)。

這意味著,不僅是AppCompatActiviy(FragmentActivity的子類)和Fragment,只要是實(shí)現(xiàn)了LifecycleOwner的類,都可以作為參數(shù)傳給AutoDispose,用以控制Observable和組件生命周期的綁定。

2、如何實(shí)現(xiàn)生命周期的綁定

參考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)行了對應(yīng)的轉(zhuǎn)化。

AutoDispose獲取了Activity(LifecycleOwner)對象,并定義了一個(gè)新的Observable,在Activity的不同生命周期中,發(fā)射對應(yīng)的事件。

和RxLifecycle很類似的是,AutoDispose在被訂閱時(shí),獲取到Activity當(dāng)前的生命周期,并找到對應(yīng)需要結(jié)束訂閱的生命周期事件:

  private static final Function<Lifecycle.Event, Lifecycle.Event> DEFAULT_CORRESPONDING_EVENTS =
      new Function<Lifecycle.Event, Lifecycle.Event>() {
        @Override public Lifecycle.Event apply(Lifecycle.Event lastEvent) throws Exception {
          switch (lastEvent) {
            case ON_CREATE:
              return Lifecycle.Event.ON_DESTROY;//比如我在onCreate到onStart之間訂閱,我會(huì)在ON_DESTROY時(shí)結(jié)束訂閱
            case ON_START:
              return Lifecycle.Event.ON_STOP;
            case ON_RESUME:
              return Lifecycle.Event.ON_PAUSE;
            case ON_PAUSE:
              return Lifecycle.Event.ON_STOP;
            case ON_STOP://如果是onPause之后訂閱,會(huì)拋出異常
            case ON_DESTROY:
            default:
              throw new LifecycleEndedException("Lifecycle has ended! Last event was " + lastEvent);
          }
        }
      };

也就是說,在我們的ObservableA訂閱時(shí),就已經(jīng)知道了自己在Activity的哪個(gè)生命周期讓AutoDispose內(nèi)部自定義的ObservableB自動(dòng)發(fā)射事件,ObservableA監(jiān)聽到這個(gè)事件時(shí)且未dispose,解除訂閱避免內(nèi)存泄漏。

畢竟內(nèi)存泄漏是少數(shù),更大的可能是ObservableA早就執(zhí)行完任務(wù)dispose了,因此ObservableB實(shí)際上就是一個(gè)Maybe,類似于

ObservableA.takeUntil( Maybe< true > )

下面為核心代碼:

 public static <E> Maybe<LifecycleEndNotification> resolveScopeFromLifecycle(
      Observable<E> lifecycle,
      final E endEvent) {
    return lifecycle.skip(1)
        .map(new Function<E, Boolean>() {
          @Override public Boolean apply(E e) throws Exception {
            return e.equals(endEvent);//是否是要解除訂閱的生命周期事件
          }
        })
        .filter(IDENTITY_BOOLEAN_PREDICATE)//篩選為true的數(shù)據(jù),即篩選解除訂閱的生命周期事件
        .map(TRANSFORM_TO_END)//轉(zhuǎn)換為LifecycleEndNotification.INSTANCE,這個(gè)枚舉只用來通知解除訂閱
        .firstElement();//返回值為Maybe,因?yàn)榭赡懿坏綄?yīng)生命周期,ObservableA就已經(jīng)完成任務(wù),onComplete() -> dispose了
  }
    
  private static final Function<Object, LifecycleEndNotification> TRANSFORM_TO_END =
      new Function<Object, LifecycleEndNotification>() {
        @Override public LifecycleEndNotification apply(Object o) throws Exception {
          return LifecycleEndNotification.INSTANCE;
        }
      };

  public enum LifecycleEndNotification {
    INSTANCE
  }

3、as方法執(zhí)行后生成了一個(gè)什么?

as方法內(nèi)部生成了一個(gè)AutoDisposeConverter對象,類似于compose,不同的是,Observable通過compose生成的對象還是Observable,但as方法生成的則是一個(gè)新的對象:

public final <R> R as(@NonNull ObservableConverter<T, ? extends R> converter)

實(shí)際上,拋開復(fù)雜的細(xì)節(jié),AutoDispose最終將原來的Observable,生成了一個(gè)新的AutoDisposeObservable對象, 在執(zhí)行訂閱時(shí),也生成了一個(gè)新的AutoDisposingObserverImpl對象,篇幅所限,不再細(xì)述。

AutoDispose和RxLifecycle的區(qū)別

從上面的原理來講,似乎AutoDispose和RxLifecycle兩者沒什么區(qū)別,原理都極為相似。

事實(shí)確實(shí)如此,因?yàn)锳utoDispose本身就是很大一部分借鑒了RxLifecycle,同時(shí),RxLifecycle的作者Daniel Lew 對于 AutoDispose的開發(fā)也有很多幫助:

以下摘錄于AutoDispose的官方文檔:

Special thanks go to Dan Lew (creator of RxLifecycle), who helped pioneer this area for RxJava in android and humored many of the discussions around lifecycle handling over the past couple years that we’ve learned from. Much of the internal scope resolution mechanics of
AutoDispose are inspired by RxLifecycle.

那么,究竟是什么原因,讓RxLifecycle的作者Daniel Lew 在他自己的文章中,羅列出RxLifecycle在開發(fā)中的窘境,并同時(shí)強(qiáng)烈推薦使用AutoDispose呢?

I'm going to keep maintaining RxLifecycle because people are still using it (including Trello), but in the long term I'm pulling away from it. For those still wanting this sort of library, I would suggest people look into AutoDispose, since I think it is better architecturally than RxLifecycle.
(我將會(huì)繼續(xù)維護(hù)RxLifecycle因?yàn)楹芏嗳硕荚谑褂盟?,但是我?huì)漸漸放棄這個(gè)庫,我建議大家可以參考AutoDispose,因?yàn)槲艺J(rèn)為它的設(shè)計(jì)更加優(yōu)秀 )

壓倒性優(yōu)勢?

我們來看看RxLifecycle的局限性:

1、需要繼承父類(RxActivity / RxFragment等)

對于設(shè)計(jì)來講,【組合】的靈活度大多數(shù)情況都優(yōu)于【繼承】,而RxLifecycle在父類中聲明了一個(gè)PublishSubject,用來發(fā)射生命周期事件,這是導(dǎo)致其局限性的原因之一。

2、如何處處綁定生命周期?

最簡單的例子,我的RecyclerView的Adapter中訂閱了Observable,亦或者,在MVP的架構(gòu)或者M(jìn)VVM架構(gòu)中,我的presenter或者我的viewModel無法直接獲取RxActivity的引用(作為View層,更應(yīng)該抽象為一個(gè)接口與Presenter進(jìn)行交互)。

這意味著,想要進(jìn)行Observable的生命周期綁定,在RecyclerView的Adapter中,我必須要通過將Activity作為依賴,注入到Adapter中:

new ListAdapter(RxActivity activity);

而對于Presenter,我需要對View抽象接口進(jìn)行instanceof 的判斷:

if (view instanceof RxActivity) {
   return bindToLifecycle((RxActivity) view);
}

當(dāng)然還有一些其他的情況,請參考原作者的文章:

Why Not RxLifecycle?

如何添加到目前的Android項(xiàng)目中(以MVP架構(gòu)為例)

AutoDispose正常直接在項(xiàng)目中使用沒有什么問題,比如:

//在Activity中使用
myObservable
    .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this))  
    .subscribe(s -> ...);

但是,在實(shí)際的生產(chǎn)環(huán)境中,我們更希望有一個(gè)良好的方式,能夠達(dá)到統(tǒng)一管理Observable綁定生命周期的效果,在此筆者以MVP的架構(gòu)為例,拋磚引玉,希望能夠獲得大家的意見和建議。

1、封裝Util類

首先封裝Util類,將職責(zé)賦予RxLifecycleUtils:

public class RxLifecycleUtils {

    private RxLifecycleUtils() {
        throw new IllegalStateException("Can't instance the RxLifecycleUtils");
    }

    public static <T> AutoDisposeConverter<T> bindLifecycle(LifecycleOwner lifecycleOwner) {
        return AutoDispose.autoDisposable(
                AndroidLifecycleScopeProvider.from(lifecycleOwner)
        );
    }
}

2、面向LifecycleOwner接口

現(xiàn)在,只要持有LifecycleOwner對象,Observable都可以通過RxLifecycleUtils.bindLifecycle(LifecycleOwner)進(jìn)行綁定。

比如我們在BaseActivity/BaseFragment中添加代碼:

public abstract class BaseActivity extends AppCompatActivity implements IActivity {
    //...忽略其他細(xì)節(jié)
    protected <T> AutoDisposeConverter<T> bindLifecycle() {
        return RxLifecycleUtils.bindLifecycle(this);
    }
}

這樣,在任何BaseActivity的實(shí)現(xiàn)類中,我們都可以通過下述代碼實(shí)現(xiàn)Observable的生命周期綁定:

myObservable
    .as(bindLifecycle())  
    .subscribe(s -> ...);

但是這樣的行為意義不大,我們更希望在Presenter中也能夠像上述代碼一樣達(dá)到Observable生命周期的綁定,但是不持有Activity的對象的同時(shí),避免RxLifecycle中尷尬的instanceof判斷。

可行嗎,可行。

3、使用Google官方Lifecycle組件

首先讓我們的IPresenter接口實(shí)現(xiàn)LifecycleObserver接口:

public interface IPresenter extends LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreate(@NotNull LifecycleOwner owner);
    
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestroy(@NotNull LifecycleOwner owner);

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onLifecycleChanged(@NotNull LifecycleOwner owner,
                            @NotNull Lifecycle.Event event);
}

然后在BasePresenter中管理LifecycleOwner:

public class BasePresenter<V extends IView, M extends IModel> implements IPresenter {

    @Getter
    protected V mRootView;

    @Getter
    protected M mModel;

    private LifecycleOwner lifecycleOwner;

    public BasePresenter(V rootView, M model) {
        this.mRootView = rootView;
        this.mModel = model;
    }

    protected <T> AutoDisposeConverter<T> bindLifecycle() {
        if (null == lifecycleOwner)
            throw new NullPointerException("lifecycleOwner == null");
        return RxLifecycleUtils.bindLifecycle(lifecycleOwner);
    
    public void onCreate(@NotNull LifecycleOwner owner) {
        this.lifecycleOwner = owner;
    }
    
    public void onDestroy(@NotNull LifecycleOwner owner) {
            if (mModel != null) {
                mModel.onDestroy();
                this.mModel = null;
            }
            this.mRootView = null;
        }
    }

最后在Activity中添加Presenter為觀察者,觀察Activity的生命周期

public abstract class BaseActivity<P extends IPresenter> extends AppCompatActivity implements IActivity {
    
    @Inject
    protected P presenter;

        @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
        //...忽略其他代碼,比如ButterKnife、Dagger2等
        lifecycle.addObserver(presenter);
    }       

    protected <T> AutoDisposeConverter<T> bindLifecycle() {
        return RxLifecycleUtils.bindLifecycle(this);
    }
}

這樣,我們即使在Presenter中,也能任意使用myObservable.as(bindLifecycle()) 方法了,和RxLifecycle相比,更加靈活。

篇幅所限,僅以最簡單的設(shè)計(jì)思路進(jìn)行闡述,更多情況的使用請?jiān)陧?xiàng)目中自行拓展。

更詳細(xì)的使用,請參考我的個(gè)人MVP架構(gòu):MvpArchitecture-Android

2018.9追加

時(shí)隔數(shù)月,我的個(gè)人MVP架構(gòu):MvpArchitecture-Android 已經(jīng)無法滿足我個(gè)人開發(fā)的需求,于我而言它更像是一個(gè)demo,因此我停止了對它的維護(hù)。

相比前者,我更喜歡MVVM架構(gòu)中AutoDispose的這次實(shí)踐,它更趨近我理想中的設(shè)計(jì),更加ReactiveFunctional

MVVM-Rhine:The MVVM Architecture in Android.

小結(jié)

事實(shí)上AutoDispose還有很多優(yōu)秀的設(shè)計(jì)點(diǎn),在源碼中得以體現(xiàn)(包括自己實(shí)現(xiàn)Observable和其Observer,以及通過代理對內(nèi)部的Observable進(jìn)行封裝,對原子操作類的靈活運(yùn)用 等等)。

但無論是RxLifecycle,AutoDispose,亦或者是自己封裝的util類,對于項(xiàng)目來說,只要滿足需求,并無優(yōu)劣之分,我們更希望能夠從一些他人的框架中,學(xué)習(xí)到他們設(shè)計(jì)的思想,和良好的代碼風(fēng)格,便足矣。

歡迎拍磚,一起探討進(jìn)步。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容