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<String>() {
@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<String>() {
    @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地址: 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中显示出来
    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.<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
    }

    可以看出FragmentEventActivityEvent 类似,都是枚举类,用法是一样的。这里就不举例了!

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

RxJava 和 RxAndroid (生命周期控制和内存优化)的更多相关文章

  1. RxJava 和 RxAndroid 三(生命周期控制和内存优化)

    rxjava rxandroid 赵彦军 前言:对Rxjava.Rxandroid不了解的同学可以先看看 RxJava 和 RxAndroid RxJava 和 RxAndroid 二(操作符的使用) ...

  2. UIViewController生命周期控制

    UIViewController生命周期控制 UIViewController介绍 官方的介绍例如以下 The UIViewController class provides the fundamen ...

  3. Newbe.Claptrap 框架如何实现多级生命周期控制?

    Newbe.Claptrap 框架如何实现多级生命周期控制?最近整理了一下项目的术语表.今天就谈谈什么是 Claptrap Lifetime Scope. 特别感谢 kotone 为本文提供的校对建议 ...

  4. Vue.js 子组件的异步加载及其生命周期控制

    前端开发社区的繁荣,造就了很多优秀的基于 MVVM 设计模式的框架,而组件化开发思想也越来越深入人心.这其中不得不提到 Vue.js 这个专注于 VM 层的框架. 本文主要对 Vue.js 组件化开发 ...

  5. 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控

    如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...

  6. iOS UIViewController生命周期控制

    具体流程,看下图: init方法在init方法中实例化必要的对象(遵从LazyLoad思想)init方法中初始化ViewController本身 loadView方法当view需要被展示而它却是nil ...

  7. UIViewController生命周期控制-开发规范

    从网上各位iOS们收集并总结: 各方法使用: init 中初始化一些UI组件,比如UIButton,UILabel等 loadView 中 createFields 接受参数,初始化变量 create ...

  8. RxJava 和 RxAndroid 五(线程调度)

    对rxJava不了解的同学可以先看 RxJava 和 RxAndroid 一 (基础)RxJava 和 RxAndroid 二(操作符的使用)RxJava 和 RxAndroid 三(生命周期控制和内 ...

  9. RxJava 和 RxAndroid 四(RxBinding的使用)

    对Rxjava不熟悉的同学可以先看我之前写的几篇文章 RxJava 和 RxAndroid 一 (基础) RxJava 和 RxAndroid 二(操作符的使用) RxJava 和 RxAndroid ...

随机推荐

  1. JavaWeb知识回顾-使用IDEA开发一个servlet.

    刚刚开始学习使用IDEA进行开发,好多都不会,本来想直接导入一个eclipse项目,但是出现了好多错误,一时不知道怎么修改,所以就从最基本的servlet开始着手,慢慢熟悉这个工具,下面是使用IDEA ...

  2. 邂逅Sass和Compass之Compass篇

    本文主要讲解Compass的内容,众所周知Compass是Sass的工具库,如果对Sass不甚了解的同学可以移步 邂逅Sass和Compass之Sass篇 Sass本身只是一个“CSS预处理器”,Co ...

  3. Hadoop(六)MapReduce的入门与运行原理

    一 MapReduce入门 1.1 MapReduce定义 Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架: Mapreduce核心功能是将用 ...

  4. TCP和UDP发送数据包的大小问题

    用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535-20-8=65507字节,其中20字节为IP包头长度,8字节为UDP包头长度.用sendto函数发送数据时,如果指的的数据长度 ...

  5. JS 数据类型转换以其他

    JavaScript 是一种弱类型的语言,也就是没有类型限制,变量可以随时被赋予任意值. 同时,在程序运行过程中,类型会被自动确认的.因此,这就是涉及到数据的类型转换.在 JS 的世界中,数据类型转换 ...

  6. 【LOJ】#2006. 「SCOI2015」小凸玩矩阵

    题解 又是美好的一天,我今天的小目标是LOJ刷题数名次前进两名(虽然巨佬们都是BZOJ千题啊这样的><,我就在LOJ划划水吧,我永远喜欢LOJ 这道题要求K大值最小,又是什么什么大值最小, ...

  7. bzoj 1176 CDQ分治

    思路:首先我们将问题转换一下,变成问在某个点左下角的权值和,那么每一个询问可以拆成4的这样的询问,然后 进行CDQ 分治,回溯的时候按x轴排序,然后用树状数组维护y的值. #include<bi ...

  8. C++运算符重载规则

    运算符重载时要遵循以下规则:  ( 1 ) 除了类属关系运算符 " . " .成员指针运算符 " .* " .作用域运算符 " :: " . ...

  9. 使用webgl(three.js)创建3D机房,3D机房微模块详细介绍(升级版二)

    序: 上节课已经详细描述了普通机房的实现过程,文章地址(https://www.cnblogs.com/yeyunfei/p/10473021.html) 紧接着上节课的内容 我们这节可来详细讲解机房 ...

  10. Hibernate fetching strategies(抓取策略)

    抓取策略(fetching strategies)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略.抓取策略可以在O/R映射的 ...