RxJava RxLifecycle 生命周期 內存泄漏 MD


Markdown版本筆記 我的GitHub首頁 我的博客 我的微信 我的郵箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

RxJava RxLifecycle 生命周期 內存泄漏 MD
Demo地址
GitHub


目錄

簡介

另一個功能與此庫類似、核心設計借鑒此庫、此庫作者也參與設計、此庫作者認為比此庫好、但是星星比較少、國內不流行、上手比較難的庫:https://github.com/uber/AutoDispose

添加依賴

implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'

完整依賴項:

implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2' //基礎庫
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2' //Android中使用的庫,內部引用了基礎庫,如果使用此庫則無需再引用基礎庫
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2' //Android組件庫,里面定義了例如RxActivity、RxFragment等Android組件,內部引用了基礎庫和Android庫,如果使用此庫則無需再重復引用
implementation 'com.trello.rxlifecycle2:rxlifecycle-components-preference:2.2.2' // Android使用的庫,繼承NaviActivity使用
implementation 'com.trello.rxlifecycle2:rxlifecycle-navi:2.2.2' //Android使用的庫,繼承LifecycleActivity使用,需要引入Google的倉庫支持
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2' //使用AndroidLifecycle
implementation 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.2' // 支持Kotlin語法的RxLifecycle基礎庫
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.2' // 支持Kotlin語法的Android庫

產生背景

隨着 RxJava 及 RxAndroid 的逐漸推廣,使用者越來越多,但是有一個問題,RxJava 的使用不當極有可能會導致內存泄漏,通常我們會有如下幾種解決方案:

  • 解決方案1:手動為 RxJava 的每一次訂閱進行控制,在指定的時機進行取消訂閱。這種情況在訂閱比較少的情況下沒問題,但是如果非常多,沒有意義的臟代碼會讓你寫到吐。
  • 解決方案2:在 BaseActivity 中記錄一個 List<Subscription> 或 List<Disposable>,每次使用后 add 進隊列,在頁面 onDestory 統一 unsubscribe() 或 dispose()。但是從一開始就發現這個方法實在是太搓了,臟代碼並沒有減少。
  • 解決方案3:后來發現很多人用一個類 CompositeSubscription,然而發現這個類僅僅是幫我們維護了一個 Set 而已,你妹,看起來高大上的樣子,實際上屁都不是!

RxLifecycle 就是專門解決這一痛點的。一開始發現要讓我們的 Activity 或 Fragment 繼承自庫中的類,就比較擔心局限性,后來發現,這貨這么做完全是為了幫我們省事呀,我們常用的一些比如 FragmentActivity、AppCompatActivity 等,基本都有相應的 Rx*** 類,實際使用時,我們只需將我們的 BaseActivity 改為實現它就行了。

該庫允許基於另一個生命周期流[a second lifecycle stream]自動完成序列[automatically complete sequences]
此功能在Android中很有用,因為在Android中,不完整的訂閱[incomplete subscriptions]可能導致內存泄漏。

注意

注意:【RxLifecycle 的原理是不是基於自動調用 unsubscribe 的】

RxLifecycle實際上並沒有取消訂閱[unsubscribe]序列。 相反,它終止[terminates]了序列。 它的表現方式因類型而異:

  • Observable、Flowable 和 Maybe:發出 onCompleted()
  • Single 和 Completable:發出onError(CancellationException)

如果序列需要 Subscription.unsubscribe() 行為,則建議您自己手動處理訂閱並在適當時調用unsubscribe()。

使用方式 compose

您必須以表示生命周期流的 Observable <T> 開頭。 然后使用 RxLifecycle 將序列綁定到該生命周期。

您可以在生命周期發出任何內容時進行綁定:

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

或者您可以在特定生命周期事件發生時綁定:
```java
myObservable
    .compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
    .subscribe(...);
 ```

或者,您可以讓 RxLifecycle 確定結束序列的適當時間:
```java
myObservable
    .compose(RxLifecycleAndroid.bindActivity(lifecycle))
    .subscribe(...);
 ```
它假定您想要在相反的`[opposing]`生命周期事件中結束序列 - 例如,如果在 START 期間訂閱,它將在 STOP 時終止。如果您在 PAUSE 之后訂閱,它將在下一個銷毀事件`[destruction event]`中終止,例如,PAUSE 將在 STOP 中終止。

# RxLifecycle
生命周期來自哪里? 通常,它們由適當的 `LifecycleProvider <T>` 提供。 但他們的實現`[implemented]`在哪里?

你有幾個選擇:
- 使用 rxlifecycle-components 中提供的 RxActivity,RxFragment 等類的子類
```java
public class MyActivity extends RxActivity {
    @Override
    public void onResume() {
        super.onResume();
        myObservable
            .compose(bindToLifecycle()) //使用內置的 bindToLifecycle() 或 bindUntilEvent() 方法即可
            .subscribe(...);
    }
}
  • 使用 Navi + rxlifecycle-navi 生成:
public class MyActivity extends NaviActivity {
    private final LifecycleProvider<ActivityEvent> provider = NaviLifecycle.createActivityLifecycleProvider(this);
    @Override
    public void onResume() {
        super.onResume();
        myObservable
            .compose(provider.bindToLifecycle())
            .subscribe();
    }
}
  • 使用 Android 的 lifecycle + rxlifecycle-android-lifecycle 生成
public class MyActivity extends LifecycleActivity {
    private final LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(this);
    @Override
    public void onResume() {
        super.onResume();
        myObservable
            .compose(provider.bindToLifecycle())
            .subscribe();
    }
}
  • 自己編寫實現

案例

public class RxBindingActivity extends RxFragmentActivity {
    private Button btn;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxbinding);

        btn = findViewById(R.id.btn);
        RxView.clicks(btn) //點擊獲取驗證碼
                .doOnNext(o -> btn.setEnabled(false))
                .subscribe(o -> Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
                        .take(10)
                        .compose(bindToLifecycle()) //綁定生命周期
                        .subscribe(aLong -> btn.setText(10 - aLong + " 秒"),
                                Throwable::printStackTrace,
                                () -> {
                                    btn.setEnabled(true);
                                    btn.setText("重新獲取");
                                }));        
    }

    @Override
    protected void onResume() {
        super.onResume();
        RxView.clicks(btn)
                .buffer(1000, TimeUnit.MILLISECONDS, 5) //效果僅僅是,每隔1秒鍾收集一下此1秒鍾內的點擊次數
                .compose(bindUntilEvent(ActivityEvent.STOP))//在 onStop 時取消
                .subscribe(list -> Log.i("【bqt】", "一秒鍾內的點擊次數:" + list.size()));
    }
}

2018-9-15


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM