前言:對Rxjava、Rxandroid不瞭解的同窗能夠先看看
RxJava 和 RxAndroid
RxJava 和 RxAndroid 二(操做符的使用)html
RxJava使咱們很方便的使用鏈式編程,代碼看起來既簡潔又優雅。可是RxJava使用起來也是有反作用的,使用愈來愈多的訂閱,內存開銷也會變得很大,稍不留神就會出現內存溢出的狀況,這篇文章就是介紹Rxjava使用過程當中應該注意的事項。java
subscription.unsubscribe()
;package lib.com.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import rx.Observable; import rx.Subscription; import rx.functions.Action1; public class MainActivity extends AppCompatActivity { Subscription subscription ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); subscription = Observable.just( "123").subscribe(new Action1<String>() { @Override public void call(String s) { System.out.println( "tt--" + s ); } }) ; } @Override protected void onDestroy() { super.onDestroy(); //取消訂閱 if ( subscription != null ){ subscription.unsubscribe(); } } }
Scheduler調度器,至關於線程控制器android
Schedulers.immediate()
: 直接在當前線程運行,至關於不指定線程。這是默認的 Scheduler。git
Schedulers.newThread()
:老是啓用新線程,並在新線程執行操做.github
Schedulers.io()
:I/O 操做(讀寫文件、讀寫數據庫、網絡信息交互等)所使用的 Scheduler。行爲模式和 newThread() 差很少,區別在於 io() 的內部實現是是用一個無數量上限的線程池,能夠重用空閒的線程,所以多數狀況下 io() 比 newThread() 更有效率。不要把計算工做放在 io() 中,能夠避免建立沒必要要的線程。web
Schedulers.computation()
: 計算所使用的 Scheduler。這個計算指的是 CPU 密集型計算,即不會被 I/O 等操做限制性能的操做,例如圖形的計算。這個 Scheduler 使用的固定的線程池,大小爲 CPU 核數。不要把 I/O 操做放在 computation() 中,不然 I/O 操做的等待時間會浪費 CPU。數據庫
還有RxAndroid裏面專門提供了AndroidSchedulers.mainThread()
,它指定的操做將在 Android 主線程運行。編程
常見的場景:爲了避免阻塞UI,在子線程加載數據,在主線線程顯示數據網絡
Observable.just( "1" , "2" , "3" ) .subscribeOn(Schedulers.io()) //指定 subscribe() 發生在 IO 線程 .observeOn( AndroidSchedulers.mainThread() ) //指定 Subscriber 的回調發生在主線程 .subscribe(new Action1<String>() { @Override public void call(String s) { textView.setText( s ); } }) ;
上面這段代碼,數據"1"、"2"、"3"將在io線程中發出,在android主線程中接收數據。這種【後臺獲取數據,前臺顯示數據】模式適用於大多數的程序策略。app
Scheduler 自由屢次切換線程。恩,這個更爲牛逼
Observable.just(1, 2, 3, 4) // IO 線程,由 subscribeOn() 指定 .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .map(mapOperator) // 新線程,由 observeOn() 指定 .observeOn(Schedulers.io()) .map(mapOperator2) // IO 線程,由 observeOn() 指定 .observeOn(AndroidSchedulers.mainThread) .subscribe(subscriber); // Android 主線程,由 observeOn() 指定
從上面的代碼能夠看出
observeOn()
能夠調用屢次來切換線程,observeOn 決定他下面的方法執行時所在的線程。
subscribeOn()
用來肯定數據發射所在的線程,位置放在哪裏均可以,但它是隻能調用一次的。
上面介紹了兩種控制Rxjava生命週期的方式,第一種:取消訂閱 ;第二種:線程切換 。這兩種方式都能有效的解決android內存的使用問題,可是在實際的項目中會出現不少訂閱關係,那麼取消訂閱的代碼也就愈來愈多。形成了項目很難維護。因此咱們必須尋找其餘可靠簡單可行的方式,也就是下面要介紹的。
github地址: https://github.com/trello/RxLifecycle
在android studio 裏面添加引用
compile 'com.trello:rxlifecycle-components:0.6.1'
讓你的activity繼承RxActivity
,RxAppCompatActivity
,RxFragmentActivity
讓你的fragment繼承RxFragment
,RxDialogFragment
;下面的代碼就以RxAppCompatActivity
舉例
bindToLifecycle
方法
在子類使用Observable中的compose操做符,調用,完成Observable發佈的事件和當前的組件綁定,實現生命週期同步。從而實現當前組件生命週期結束時,自動取消對Observable訂閱。
public class MainActivity extends RxAppCompatActivity { TextView textView ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); //循環發送數字 Observable.interval(0, 1, TimeUnit.SECONDS) .subscribeOn( Schedulers.io()) .compose(this.<Long>bindToLifecycle()) //這個訂閱關係跟Activity綁定,Observable 和activity生命週期同步 .observeOn( AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { System.out.println("lifecycle--" + aLong); textView.setText( "" + aLong ); } }); } }
上面的代碼是Observable循環的發送數字,而且在textview中顯示出來
一、沒加 compose(this.<Long>bindToLifecycle())
當Activiry 結束掉之後,Observable仍是會不斷的發送數字,訂閱關係沒有解除
二、添加compose(this.<Long>bindToLifecycle())
當Activity結束掉之後,Observable中止發送數據,訂閱關係解除。
從上面的例子能夠看出bindToLifecycle()
方法可使Observable發佈的事件和當前的Activity綁定,實現生命週期同步。也就是Activity 的 onDestroy() 方法被調用後,Observable 的訂閱關係才解除。那能不能指定在Activity其餘的生命狀態和訂閱關係保持同步,答案是有的。就是 bindUntilEvent()
方法。這個逼裝的好累!
bindUntilEvent( ActivityEvent event)
ActivityEvent.CREATE
: 在Activity的onCreate()方法執行後,解除綁定。
ActivityEvent.START
:在Activity的onStart()方法執行後,解除綁定。
ActivityEvent.RESUME
:在Activity的onResume()方法執行後,解除綁定。
ActivityEvent.PAUSE
: 在Activity的onPause()方法執行後,解除綁定。
ActivityEvent.STOP
:在Activity的onStop()方法執行後,解除綁定。
ActivityEvent.DESTROY
:在Activity的onDestroy()方法執行後,解除綁定。
//循環發送數字 Observable.interval(0, 1, TimeUnit.SECONDS) .subscribeOn( Schedulers.io()) .compose(this.<Long>bindUntilEvent(ActivityEvent.STOP )) //當Activity執行Onstop()方法是解除訂閱關係 .observeOn( AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { System.out.println("lifecycle-stop-" + aLong); textView.setText( "" + aLong ); } });
通過測試發現,當Activity執行了onStop()方法後,訂閱關係已經解除了。
上面說的都是訂閱事件與Activity的生命週期同步,那麼在Fragment裏面又該怎麼處理的?
FragmentEvent
這個類是專門處理訂閱事件與Fragment生命週期同步的大殺器
public enum FragmentEvent { ATTACH, CREATE, CREATE_VIEW, START, RESUME, PAUSE, STOP, DESTROY_VIEW, DESTROY, DETACH }
能夠看出FragmentEvent
和 ActivityEvent
相似,都是枚舉類,用法是同樣的。這裏就不舉例了!
總結
一、這三篇文章的相關代碼示例都在 http://git.oschina.net/zyj1609/RxAndroid_RxJava
二、經過上面的三種方法,我相信你在項目中使用Rxjava的時候,已經可以很好的控制了 Rxjava對內存的開銷。若是你有其餘的方法或者問題,能夠留言給我。