前言:对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对内存的开销。若是你有其余的方法或者问题,能够留言给我。