rxjava
rxandroid
赵彦军

前言:对Rxjava、Rxandroid不了解的同学可以先看看
RxJava 和 RxAndroid
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<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 四(RxBinding的使用)

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

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

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

  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. vue学习三:生命周期钩子

    生命周期钩子介绍: 每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等.同时在这个过程中也会运行一些叫做生 ...

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

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

  7. Docker 基本概念(三)-生命周期详解(镜像、容器、仓库)

    Docker三大组件:镜像.容器.仓库.  一.镜像 1 从仓库获取镜像 #一.从仓库获取镜像,帮助命令:docker pull -help 命令:docker pull [选项] [docker R ...

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

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

  9. iOS UIViewController生命周期控制

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

随机推荐

  1. C# 控制台或者winform程序开启http的监听状态

    1 public class THttpListener { HttpListener listerner; /// <summary> /// /// </summary> ...

  2. 【Android】使用属性动画碰到的困惑及讲解

    属性动画的教程网上已经特别多了,本篇也不打算再去各种详解知识点,主要就是记录题主学习属性动画时的碰到的一些困惑,以及后来自己的理解.如果有人也碰到相似的问题,正好可以一起讨论下. 概要 本篇主要涉及的 ...

  3. 使用Microsoft Fakes进行单元测试(1)

    一:什么是单元测试 单元测试是对软件进行准确性验证的步骤.单元测试并不进行整个软件功能的测试,仅仅是对于最小工作单元的测试.一般最小工作单元就是指方法/函数等. 这里并不打算对单元测试的概念及基础进行 ...

  4. SQL--类型转换

    Convert函数和Cast函数都是转化函数,效果是一样的. cast函数,转化,如果转化之后,年龄还是Null的话,就显示为“未知” Convert函数和Cast函数都是转化函数,效果是一样的.

  5. 【转】sql server 获取每一个类别中值最大的一条数据

    /* 数据如下: name val memo a 2 a2(a的第二个值) a 1 a1--a的第一个值 a 3 a3:a的第三个值 b 1 b1--b的第一个值 b 3 b3:b的第三个值 b 2 ...

  6. 判断JS对象是否拥有某属性

    两种方式,但稍有区别 1.in 运算符  

  7. CSRF 攻击介绍

    CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/ ...

  8. 一不小心把oschina给戒了

    不知怎么回事,逐渐变成一周看一次oschina了.

  9. SDL制作拼图游戏

    看完教程第三集后,好像自己能用这个来写一个简单的拼图游戏,第一次写出个带界面的游戏,好有成就感. 图片是自己慢慢截左上部分8个脸. #include <stdio.h> #include ...

  10. Guava学习笔记:Immutable(不可变)集合

    不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 1.对不可靠的客 ...