1. 程式人生 > >Rxlifecycle的引入和原理說明

Rxlifecycle的引入和原理說明

一.背景 在專案中使用Retrofit+Rxjava的過程中,如果程式碼編寫思量不夠就會引入記憶體洩漏。對記憶體的解決方案目前存在三種,第一種是在適當的時候解除對網路請求的訂閱;第二種是採用RxlifeCycle;第三種是採用AutoDisPose。二.Retrofit和Rxjava使用中的記憶體洩漏 在說明Retrofit和Rxjava的記憶體洩漏前,先檢視一下它們結合使用的常用程式碼如下:
//Service介面的程式碼publicinterfaceServiceApi {@GET("/user/info") Observable<Response> getUserInfo
(@Query("userId") String userId);}//Activity通過Retrofit獲取使用者資訊,Retrofit的構造資訊在此略過privatevoidgetUserInfo(){ subscription = serviceApi.getUserInfo("001") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Response>() {@Override
publicvoidcall(Response response) { String content = new String(((TypedByteArray) response.getBody()).getBytes()); userInfo.setText(content); } }, new Action1<Throwable>() {@Overridepublicvoidcall(Throwable throwable) { throwable.printStackTrace();
} });}
上面是很常見的Retrofit和Rxjava結合使用的程式碼,上面使用的程式碼中有一個問題就是subscribe函式中的內部物件"new Action"會持有了Activity的引用,如果在關閉Activity過程中,retrofit的網路請求仍在繼續,內部物件Activity1對Activity仍然持有引用,就會導致Activity物件不會被銷燬造成記憶體洩漏。三.記憶體洩漏的解決方案 第一種方案:解除對網路請求的訂閱
//在Activity通過Retrofit獲取使用者資訊,Retrofit的構造資訊在此略過privatevoidgetUserInfo(){ subscription = serviceApi.getUserInfo("001") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .onTerminateDetach() //在取消訂閱時解除上游生成者和下游訂閱者間的引用 .subscribe(new Action1<Response>() {@Overridepublicvoidcall(Response response) { String content = new String(((TypedByteArray) response.getBody()).getBytes()); userInfo.setText(content); } }, new Action1<Throwable>() {@Overridepublicvoidcall(Throwable throwable) { throwable.printStackTrace(); } });}@OverridepublicvoidonDestroy() {super.onDestroy();if (subscription != null && !subscription.isUnsubscribed()) {subscription.unsubscribe(); //在Activity結束時解除訂閱關係 }}
第一種方案實施起來,要麼在每個使用Retrofit的Activity頁面中都進行一次解除訂閱,要麼自己完成一個程式碼的封裝。如果採用Rxlifecycle或AutoDispose程式碼就會簡潔和可靠很多。 第二種方案:採用Rxlifecycle框架 第三種方案:採用AutoDispose框架四.Rxlifecycle的原理說明 1.Activity中呼叫Rxlifecycle的程式碼如下:
// Specifically bind this until onPause()Observable.interval(1, TimeUnit.SECONDS) .doOnDispose(new Action() {@Overridepublic void run() throws Exception { Log.i(TAG, "Unsubscribing subscription from onCreate()"); } }) .compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE)) //指定在Activity呼叫onPause時解除對事件的繫結 .subscribe(new Consumer<Long>() {@Overridepublic void accept(Long num) throws Exception { Log.i(TAG, "Started in onCreate(), running until onPause(): " + num); } });
2.compose是對Observable觀察流進行轉換,將一類Observable轉換成另一類Observable,檢視bindUntilEvent程式碼如下:
@Override@NonNull@CheckResultpublic final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {return RxLifecycle.bindUntilEvent(lifecycleSubject, event);}
其中lifecycleSubject屬於另一個Observable,會在Activity生命週期的每一個階段發出事件來。3.繼續跟蹤原始碼bindUntileEvent,如下,可以看到在lifecycle返回和event相同的事件時,才會返回一個Observable。
*/@Nonnull@CheckReturnValuepublic 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>() {@Overridepublic boolean test(R lifecycleEvent) throws Exception {return lifecycleEvent.equals(event); } });}
4.上面的bindUntilEvent會返回一個LifecycleTransformer物件,該物件在bind函式中生成,在LifecycleTransform類中實現了介面函式apply
@Nonnull // bind函式@CheckReturnValuepublic static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {return new LifecycleTransformer<>(lifecycle);}
@ParametersAreNonnullByDefaultpublic 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; }@Overridepublic ObservableSource<T> apply(Observable<T> upstream) { //apply介面函式的實現return upstream.takeUntil(observable); }
apply函式會在compose呼叫的時候去執行。takeUntil表示當observable傳送事件流的時候,upstream就會停止傳送事件流,並解除上下流之間的引用關係。五.總結 方案二的實現過程就是,在呼叫時指定一個Activity的截止事件;在基類中構造一個產生事件的Observable,該Observable傳送流的時機在選擇在所產生的事件等於截止事件時;然後在呼叫的實現方法中判斷當有流產生時,就截止原本的流。有點繞,但是大致是這麼個意思。方案三和方案二的實現原理類似,區別在於方案二需要通過繼承RxAppCompatActivity或RxFragment來實現,而方案三則只需以組合的方式就可以完成,靈活性要高於方案二。參考連結