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: 愿以渺小启程以平凡完结