Android Rx家族之RxLifecycle管理生命周期 解决RxJava内存泄漏

1.1.使用原因。

  在使用rxjava的时候,如果没有及时解除订阅,在退出activity的时候,异步线程还在执行。

  对activity还存在引用,此时就会产生内存泄漏。

  RxLifecycle就是为了解决rxjava导致的内存泄漏而产生的。

 

1.为什么会发生内存泄漏

使用RxJava发布一个订阅后,当页面被finish,此时订阅逻辑还未完成,如果没有及时取消订阅,就会导致Activity/Fragment无法被回收,从而引发内存泄漏。

 

RxLifecycle是什么

大概意思就是:可以通过绑定生命周期的方式,来解决内存泄漏的问题。

 

1.2.RxLifecycle可以做到什么呢?  

  它可以让Observable发布的事件和当前的组件绑定,实现生命周期同步。

  从而实现当前组件生命周期结束时,自动取消对Observable订阅。

  核心思想:通过监听Activity、Fragment的生命周期,来自动断开订阅防止内存泄漏。
 

2.使用方法

 

2.1.添加最新的依赖 

//rxjava的依赖
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
//rxlifecycle的依赖
compile 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.1'

 

 

2.2.Activity以及Fragment的继承

  Activity需要继承RxAppCompatActivity。==>比如这么一个类

public class BaseActivity extends RxAppCompatActivity

  Fragment需要继承RxFragment。==>比如这么一个类

public abstract class BaseFragment<T extends IBasePresenter>
        extends RxFragment
        implements IBaseView<T>

 

 

2.3.绑定生命周期。

  自己写一个接口,里面定义一个bindToLife()函数。  

 /**
     * 绑定生命周期
     */
    <T> LifecycleTransformer<T> bindToLife();

  这个bindToLife()是自定义的名字,这里就叫做bindToLife好了。

  这个接口是自己定义的一个接口,我让Fragment来继承这个接口。

  这个返回的是一个LifecycleTransformer<T>,这个官方的一个类。而且这里使用了泛型,更加通用了。

 

 

2.4.在自己的Fragment中实现这个接口函数。 

/**
     * 绑定生命周期
     */
    @Override
    public <T> LifecycleTransformer<T> bindToLife() {
        return bindUntilEvent(FragmentEvent.DESTROY);
    }

  这里调用了官方的一个bindUntilEvent的方法,以此函数来绑定生命周期。

  这里的FragmentEvent.DESTROY,顾名思义,就是当Fragment销毁的时候,自动解除订阅关系。

  

  注意:这里使用了FragmentEvent类,其中的CREATE/START/RESUME/PAUSE/STOP/DESTROY  

        分布对应生命周期内的方法。使用bindUntilEvent指定在哪个生命周期方法调用示取消订阅。

 

 

2.5.在请求API函数的时候,执行自己写的bindToLife()

    调用Observable<T>.compose(执行接口中的bindToLife())

  compose里面的东西应该是:LifecycleTransformer<T>。

 

 

原理:

RxLifecycle基本原理:

 

首先bindToLifecycle是通过compose操作的,compose操作符比较常见,比如切换线程的时候,用compose操作符让代码更好看些,compose操作的是个Transformer,跟进去看,bindToLifecycle果然返回一个封装了的LifecycleTransformer:

 

3.对于Rxlifecycle的理解

3.1.使用原因就不用多说了,解决RxJava导致的内存泄漏。

 

 

3.2.因为activity和fragment控制切换线程的时候,引用没有清除干净,所以就把手脚着重于activity和fragment的

  生命周期了,就是说,如果你的活动如果碰到意外或者用户主动销毁,那么也断开订阅,就是订阅的生命周期

  和活动的生命周期已经融为一体了,那就不用担心再发生内存泄漏了,所以这种绑定生命周期的方法是从根本

  上解决了内存泄漏。感觉没有更好的方法解决了。

 

 

3.3.其实官方为了两种解决方案。

  一种是手动取消订阅,我不知道怎么用,也没有实战过。

  这里提供一下大神的文章:RxAndroid之Rxlifecycle使用。

  手动设置在activity onPause的时候取消订阅。

private static final String TAG = "RxLifecycle";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d(TAG, "onCreate()");
    setContentView(R.layout.activity_main);

    Observable.interval(1, TimeUnit.SECONDS)
            .doOnUnsubscribe(new Action0() {
                @Override
                public void call() {
                    Log.i(TAG, "Unsubscribing subscription from onCreate()");
                }
            })
            //Note:手动设置在activity onPause的时候取消订阅
            .compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE))
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long num) {
                    Log.i(TAG, "Started in onCreate(), running until onPause(): " + num);
                }
            });
}

 

  手动设置在activity的onDestroy的时候取消订阅。

@Override
protected void onResume() {
    super.onResume();
    Log.d(TAG, "onResume()");

    // `this.<Long>` is necessary if you're compiling on JDK7 or below.
    // If you're using JDK8+, then you can safely remove it.
    Observable.interval(1, TimeUnit.SECONDS)
            .doOnUnsubscribe(new Action0() {
                @Override
                public void call() {
                    Log.i(TAG, "Unsubscribing subscription from onResume()");
                }
            })
            //Note:手动设置在activity onDestroy的时候取消订阅
            .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long num) {
                    Log.i(TAG, "Started in onResume(), running until in onDestroy(): " + num);
                }
            });
}

 

  自动设置取消订阅,默认在onStart的时候调用,在onStop的时候取消订阅。

@Override
protected void onStart() {
    super.onStart();
    Log.d(TAG, "onStart()");// Using automatic unsubscription, this should determine that the correct time to
    // unsubscribe is onStop (the opposite of onStart).
    Observable.interval(1, TimeUnit.SECONDS)
            .doOnUnsubscribe(new Action0() {
                @Override
                public void call() {
                    Log.i(TAG, "Unsubscribing subscription from onStart()");
                }
            })
            //Note:bindToLifecycle的自动取消订阅示例,因为是在onStart的时候调用,所以在onStop的时候自动取消订阅
            .compose(this.<Long>bindToLifecycle())
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long num) {
                    Log.i(TAG, "Started in onStart(), running until in onStop(): " + num);
                }
            });
}

 

实践;

public class RxLifecycleComponentsActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxlifecycle_components);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Observable.interval(1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.<Long>bindToLifecycle())
                .subscribe();
    }
}

 

interval操作符的用法。

 

使用compose(this.<Long>bindToLifecycle())方法绑定Activity的生命周期

 

demo地址:

https://link.jianshu.com/?t=https://github.com/alidili/Demos/tree/master/RxLifecycleDemo

 

参考博客:

https://www.jianshu.com/p/7fae42861b8d

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值