博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RxJava 和 RxAndroid 三(生命周期控制和内存优化)
阅读量:7154 次
发布时间:2019-06-29

本文共 5733 字,大约阅读时间需要 19 分钟。

前言:对Rxjava、Rxandroid不了解的同学可以先看看

RxJava使我们很方便的使用链式编程,代码看起来既简洁又优雅。但是RxJava使用起来也是有副作用的,使用越来越多的订阅,内存开销也会变得很大,稍不留神就会出现内存溢出的情况,这篇文章就是介绍Rxjava使用过程中应该注意的事项。

1、取消订阅 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
() { @Override public void call(String s) { System.out.println( "tt--" + s ); } }) ; } @Override protected void onDestroy() { super.onDestroy(); //取消订阅 if ( subscription != null ){ subscription.unsubscribe(); } }}

2、线程调度

  • Scheduler调度器,相当于线程控制器

    • Schedulers.immediate() : 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。

    • Schedulers.newThread() :总是启用新线程,并在新线程执行操作.

    • Schedulers.io():I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。

    • 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
    () { @Override public void call(String s) { textView.setText( s ); } }) ;

    上面这段代码,数据"1"、"2"、"3"将在io线程中发出,在android主线程中接收数据。这种【后台获取数据,前台显示数据】模式适用于大多数的程序策略。

  • 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内存的使用问题,但是在实际的项目中会出现很多订阅关系,那么取消订阅的代码也就越来越多。造成了项目很难维护。所以我们必须寻找其他可靠简单可行的方式,也就是下面要介绍的。

3、rxlifecycle 框架的使用

  • github地址: 

  • 在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.
    bindToLifecycle()) //这个订阅关系跟Activity绑定,Observable 和activity生命周期同步 .observeOn( AndroidSchedulers.mainThread()) .subscribe(new Action1
    () { @Override public void call(Long aLong) { System.out.println("lifecycle--" + aLong); textView.setText( "" + aLong ); } }); } }

    上面的代码是Observable循环的发送数字,并且在textview中显示出来

    1、没加 compose(this.<Long>bindToLifecycle()) 当Activiry 结束掉以后,Observable还是会不断的发送数字,订阅关系没有解除
    2、添加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.
    bindUntilEvent(ActivityEvent.STOP )) //当Activity执行Onstop()方法是解除订阅关系 .observeOn( AndroidSchedulers.mainThread()) .subscribe(new Action1
    () { @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 类似,都是枚举类,用法是一样的。这里就不举例了!

总结

1、这三篇文章的相关代码示例都在 
2、通过上面的三种方法,我相信你在项目中使用Rxjava的时候,已经能够很好的控制了 Rxjava对内存的开销。如果你有其他的方法或者问题,可以留言给我。

 

    本文转自 一点点征服   博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6594599.html,如需转载请自行联系原作者
你可能感兴趣的文章
初用 Git 小问题解决备忘录
查看>>
yii 显示调试信息及数据库配置
查看>>
mysql 用户权限操作
查看>>
php练习作品-汽车多店维修预约平台
查看>>
sqlite rowid与主键
查看>>
vim 使用笔记
查看>>
Spring中Singleton模式的线程安全
查看>>
Spring整合- mongodb
查看>>
Activity 之继承学习 Fragment
查看>>
如何让你的scrapy爬虫不再被ban
查看>>
Python使用UUID库生成唯一ID
查看>>
WinSCP乱码解决
查看>>
部署在Tomcat 服务器中的web应用读取时间与系统时间不一致问题 【靠谱】
查看>>
<Tag> tld的配置
查看>>
datesheet你看懂了吗?
查看>>
第一课 redis安装配置
查看>>
ASP.NET开源博客QBlog开发者视频教程:生命周期Page_Load介绍及简洁传递参数的...
查看>>
项目成功必要条件
查看>>
ECharts简介及入门
查看>>
亿级Web系统搭建:单机到分布式集群
查看>>