Rxlifecycle的引入和原理说明

一.背景
在项目中使用Retrofit+Rxjava的过程中,如果代码编写思量不够就会引入内存泄漏。对内存的解决方案目前存在三种,第一种是在适当的时候解除对网络请求的订阅;第二种是采用RxlifeCycle;第三种是采用AutoDisPose。
二.Retrofit和Rxjava使用中的内存泄漏
在说明Retrofit和Rxjava的内存泄漏前,先查看一下它们结合使用的常用代码如下:
//Service 接口的代码
public interface ServiceApi {

@GET ( "/user/info" )
Observable<Response> getUserInfo (@Query( "userId" ) String userId);
}

// Activity 通过 Retrofit 获取用户信息, Retrofit 的构造信息在此略过
private void getUserInfo (){
subscription = serviceApi.getUserInfo( "001" )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( new Action1<Response>() {
@Override
public void call (Response response) {
String content = new String(((TypedByteArray) response.getBody()).getBytes());
userInfo.setText(content);
}
}, new Action1<Throwable>() {
@Override
public void call (Throwable throwable) {
throwable.printStackTrace();
}
});
}
上面是很常见的Retrofit和Rxjava结合使用的代码,上面使用的代码中有一个问题就是subscribe函数中的内部对象"new Action"会持有了Activity的引用,如果在关闭Activity过程中,retrofit的网络请求仍在继续,内部对象Activity1对Activity仍然持有引用,就会导致Activity对象不会被销毁造成内存泄漏。
三.内存泄漏的解决方案
第一种方案:解除对网络请求的订阅
//在Activity通过Retrofit获取用户信息,Retrofit的构造信息在此略过
private void getUserInfo (){
subscription = serviceApi.getUserInfo( "001" )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.onTerminateDetach() //在取消订阅时解除上游生成者和下游订阅者间的引用
.subscribe( new Action1<Response>() {
@Override
public void call (Response response) {
String content = new String(((TypedByteArray) response.getBody()).getBytes());
userInfo.setText(content);
}
}, new Action1<Throwable>() {
@Override
public void call (Throwable throwable) {
throwable.printStackTrace();
}
});
}

@Override
public void onDestroy () {
super .onDestroy();
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe(); //在Activity结束时解除订阅关系
}
}
第一种方案实施起来,要么在每个使用Retrofit的Activity页面中都进行一次解除订阅,要么自己完成一个代码的封装。如果采用Rxlifecycle或AutoDispose代码就会简洁和可靠很多。
第二种方案:采用Rxlifecycle框架
关于Rxlifecycle的使用介绍博客很多,比如可以参考如下博客文档: https://blog.csdn.net/mq2553299/article/details/78927617
第三种方案:采用AutoDispose框架
四.Rxlifecycle的原理说明
1.Activity中调用Rxlifecycle的代码如下:
// Specifically bind this until onPause()
Observable. interval ( 1 , TimeUnit. SECONDS )
.doOnDispose( new Action() {
@Override
public void run() throws Exception {
Log. i ( TAG , "Unsubscribing subscription from onCreate()" );
}
})
.compose( this .<Long>bindUntilEvent(ActivityEvent. PAUSE )) //指定在Activity调用onPause时解除对事件的绑定
.subscribe( new Consumer<Long>() {
@Override
public void accept(Long num) throws Exception {
Log. i ( TAG , "Started in onCreate(), running until onPause(): " + num);
}
});
2.compose是对Observable观察流进行转换,将一类Observable转换成另一类Observable,查看bindUntilEvent代码如下:
@Override
@NonNull
@CheckResult
public final < T > LifecycleTransformer< T > bindUntilEvent( @NonNull ActivityEvent event) {
return RxLifecycle. bindUntilEvent ( lifecycleSubject , event);
}

其中lifecycleSubject属于另一个Observable,会在Activity生命周期的每一个阶段发出事件来。
3.继续跟踪源码bindUntileEvent,如下,可以看到在lifecycle返回和event相同的事件时,才会返回一个Observable。
*/
@Nonnull
@CheckReturnValue
public static < T , R > LifecycleTransformer< T > bindUntilEvent( @Nonnull final Observable< R > lifecycle,
@Nonnull final R event) {
checkNotNull (lifecycle, "lifecycle == null" );
checkNotNull (event, "event == null" );
return bind ( takeUntilEvent (lifecycle, event));
}

private static < R > Observable< R > takeUntilEvent( final Observable< R > lifecycle, final R event) {
return lifecycle.filter( new Predicate< R >() {
@Override
public boolean test( R lifecycleEvent) throws Exception {
return lifecycleEvent.equals( event );
}
});
}

4.上面的bindUntilEvent会返回一个LifecycleTransformer对象,该对象在bind函数中生成,在LifecycleTransform类中实现了接口函数apply
@Nonnull // bind函数
@CheckReturnValue
public static < T , R > LifecycleTransformer < T > bind( @Nonnull final Observable< R > lifecycle) {
return new LifecycleTransformer <>(lifecycle);
}

@ParametersAreNonnullByDefault
public final class LifecycleTransformer< T > implements ObservableTransformer< T , T >,
FlowableTransformer< T , T >,
SingleTransformer< T , T >,
MaybeTransformer< T , T >,
CompletableTransformer
{
final Observable<?> observable ;

LifecycleTransformer(Observable<?> observable) {
checkNotNull (observable, "observable == null" );
this . observable = observable;
}

@Override
public ObservableSource< T > apply(Observable< T > upstream) { //apply接口函数的实现
return upstream.takeUntil( observable );
}
apply函数会在compose调用的时候去执行。takeUntil表示当observable发送事件流的时候,upstream就会停止发送事件流,并解除上下流之间的引用关系。
五.总结
方案二的实现过程就是,在调用时指定一个Activity的截止事件;在基类中构造一个产生事件的Observable,该Observable发送流的时机在选择在所产生的事件等于截止事件时;然后在调用的实现方法中判断当有流产生时,就截止原本的流。有点绕,但是大致是这么个意思。方案三和方案二的实现原理类似,区别在于方案二需要通过继承 RxAppCompatActivity或RxFragment来实现,而方案三则只需以组合的方式就可以完成,灵活性要高于方案二。
参考链接

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值