Android 解决RxJava导致内存泄露的RxLifecycle
一:前景
在使用RxJava的时候,如果没有及时的解除订阅,在退出activity的时候,异步线程还在执行。对Activity的还在引用,此时就会产生内存泄露。
RxLifecycle就是为了解决rxjava导致的内存泄漏而产生的。
1.添加依赖
//RxLifecycle
implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
2.Activity和Fragment
Activity
RxAppCompatActivity、RxActivity、RxFragmentActivity
Fragment
RxFragment、RxDialogFragment、RxPreferenceFragment、RxAppCompatDialogFragment
二:RxLifecycle使用
1.bindUntilEvent(ActivityEvent e)
public class TenActivity extends RxAppCompatActivity implements View.OnClickListener {
private Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ten);
btn=findViewById(R.id.btn);
btn.setOnClickListener(this::onClick);
}
@Override
public void onClick(View v) {
//使用RxJava,定时每3秒打印
//compose()是唯一一个能够从数据流中得到原始Observable的操作符,所以,那些需要对整个数据流产生作用的操作(比如,subscribeOn()和observeOn())需要使用compose()来实现。相较而言,如果在flatMap()中使用subscribeOn()或者observeOn(),那么它仅仅对在flatMap()中创建的Observable起作用,而不会对剩下的流产生影响
Observable.interval(3, TimeUnit.SECONDS)
.compose(bindUntilEvent(ActivityEvent.DESTROY))//通过compose绑定RxLifecycle的Activity的生命周期
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("aaa", String.valueOf(aLong));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("aaa", "onDestory()");
}
}
//打印结果
aaa: 0
aaa: 1
aaa: 2
aaa: 3
aaa: onDestory()
以上代码的意思是说,当前Activity执行到onDestroy时,Observable取消订阅
bindUntilEvent后面的参数决定Observable什么时候被取消
ActivityEvent对应的是Activity生命周期方法
public enum ActivityEvent {
CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY;
private ActivityEvent() {
}
}
2.bindToLifecycle()使用
//我们在Activity 在onResume()生命周期里点击执行RxJava每3秒打印
Observable.interval(3, TimeUnit.SECONDS)
.compose(bindToLifecycle())//使用第二种方式bindToLifecycle绑定生命周期,没有传入去生命周期,结果是在onPause下解除绑定这是为什么呢,需要源码分析
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.d("aaa", String.valueOf(aLong));
}
});
//结果:
aaa: 0
aaa: 1
aaa: 2
aaa: onPause()
源码:
private static final Function<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE = new Function<ActivityEvent, ActivityEvent>() {
public ActivityEvent apply(ActivityEvent lastEvent) throws Exception {
switch(lastEvent) {
case CREATE:
return ActivityEvent.DESTROY;
case START:
return ActivityEvent.STOP;
case RESUME:
return ActivityEvent.PAUSE;
case PAUSE:
return ActivityEvent.STOP;
case STOP:
return ActivityEvent.DESTROY;
case DESTROY:
throw new OutsideLifecycleException("Cannot bind to Activity lifecycle when outside of it.");
default:
throw new UnsupportedOperationException("Binding to " + lastEvent + " not yet implemented");
}
}
};
源码意思:
如果Observable在onCreate执行,那么当执行到onDestroy时取消订阅;
如果Observable在onStart执行,那么当执行到onStop时取消订阅;
如果Observable在onResume执行,那么当执行到onPause时取消订阅;
如果Observable在onPause执行,那么当执行到onStop时取消订阅;
如果Observable在onStop执行,那么当执行到onDestroy时取消订阅;
如果Observable在onDestroy执行,则抛出异常;
故可以解释我们在onResume()生命周期中调用,onPause()取消了订阅
三:组件化和Base库中使用RxLifecycle
我们通常需要在这封装来,不会这样单独直接在Activity中使用
我根据我之前的代码封装讲解一下
第一步:我们使用RxJava中被观察者Observable,去定义compose()来绑定生命周期
//这里我们对被观察者,即网络接口,进行分封装,compose(lifecycle.bindUntilEvent(event)),我们使用bindUntilEvent绑定生命周期方法,故需要传递2个参数,一个是 LifecycleProvider<ActivityEvent> 去调用bindUntilEvent,一个是ActivityEvent参数
public static <T> Observable<T> getObservable(
Observable<T> apiObservable,
LifecycleProvider<ActivityEvent> lifecycle,
ActivityEvent event) {
// showLog(request);
Observable<T> observable;
if (lifecycle != null) {
// 手动管理移除监听生命周期.eg:ActivityEvent.STOP
observable =
apiObservable
// 需要在这个位置添加
.compose(lifecycle.bindUntilEvent(event))
.onErrorResumeNext(new HttpResultFunction<>())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
} else {
observable = getObservable(apiObservable);
}
return observable;
}
第二步:我们在Model层进行网络请求,我们以获取验证码为例
在这里我们被观察者订阅了观察者,Rxjava实现了异步
@Override
public void getVerfitCode(LifecycleProvider<ActivityEvent> event, SendSMSBean sendSMSBean, LoginCallBack loginCallBack) {
HttpObservable.getObservable(apiService.getSMS(sendSMSBean), event, ActivityEvent.DESTROY)//主要是来分析这个的,之前需要的2个参数,event这个参数由他的调用者给,ActivityEvent.DESTROY生命周期,我们给了Destroy(),这是一个枚举类型
//那么他的调用者mvp模式下,交由P层调用传入LifecycleProvider<ActivityEvent>这个参数
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new HttpObserver<String>() {//订阅,HttpObserver观察者
@Override
public void onSuccess(String response) {
loginCallBack.getCodeSuccess(response);
}
@Override
public void onFail(boolean connect, int code, String msg) {
loginCallBack.getCodeFail(connect, code, msg);
}
@Override
public void onStart(Disposable disposable) {
}
});
}
第三步:P层实现类LoginPresenter中这个方法中传递给了Mode层实现类LoginModel中参数,那么getProvider()方法获取到了LifecycleProvider<ActivityEvent>这个参数
public void getVerfitCode(String phone, String ip, int codeType) {
SendSMSBean sendSMSBean = new SendSMSBean(phone, ip, codeType);
mode.getVerfitCode(getProvider(), sendSMSBean, this);
}
第四步:交由getProvider()获取到参数,这是在我封装的BaseProvider中实现的
private LifecycleProvider<ActivityEvent> provider;
private LifecycleProvider<FragmentEvent> fragmentProvider;
public BasePresenter(LifecycleProvider<ActivityEvent> provider,ActivityEvent event){
this.provider=provider;
}
public BasePresenter(LifecycleProvider<FragmentEvent> fragmentProvider,FragmentEvent event){
this.fragmentProvider=fragmentProvider;
}
public LifecycleProvider<ActivityEvent> getProvider(){
return provider;
}
public LifecycleProvider<FragmentEvent> getFragmentProvider(){
return fragmentProvider;
}
那么具体实现类LoginPresenter,谁实现了LoginPresenter就传递过去
public LoginPresenter(LifecycleProvider<ActivityEvent> provider, ActivityEvent event) {
super(provider, event);//调用父类
mode = new LoginModel();
}
第五步:在Activity中具体实现是LoginActivity中LoginActivity 继承BaseActivity ,BaseActivity继承RxAppCompatActivity
@Override
protected LoginPresenter loadPresenter() {
return new LoginPresenter(this, ActivityEvent.DESTROY);
}
//这里传递this代表当前Activity,即LoginActivity,是继承了RxAppCompatActivity的
如果想知道为什么this,能传入参数LifecycleProvider<ActivityEvent>,那么我们就要看RxAppCompatActivity的源码了
RxAppCompatActivity的源码
public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public RxAppCompatActivity() {
}
@ContentView
public RxAppCompatActivity(@LayoutRes int contentLayoutId) {
super(contentLayoutId);
}
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return this.lifecycleSubject.hide();
}
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(this.lifecycleSubject, event);
}
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(this.lifecycleSubject);
}
。。。。。。部分源码
//可以看到他实现了接口implements LifecycleProvider<ActivityEvent>
//故这个this,代表LoginActivity也实现了父类这个接口故绑定了LoginActivity的生命周期
// Java中子类会继承父类对于接口的实现。
}
END:愿以渺小启程以伟大结束
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。