zoukankan      html  css  js  c++  java
  • 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的使用)

  • 相关阅读:
    【转载】SAP_ECC6.0_EHP4或SAP_ECC6.0_EHP5_基于Windows_Server_2008R2_和SQL_server_2008下的安装
    使用delphi 开发多层应用(二十四)KbmMW 的消息方式和创建WIB节点
    使用delphi 开发多层应用(二十三)KbmMW 的WIB
    实现KbmMw web server 支持https
    KbmMW 服务器架构简介
    Devexpress VCL Build v2014 vol 14.1.1 beta发布
    使用delphi 开发多层应用(二十二)使用kbmMW 的认证管理器
    KbmMW 4.50.00 测试版发布
    Basic4android v3.80 beta 发布
    KbmMW 认证管理器说明(转载)
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/7561472.html
Copyright © 2011-2022 走看看