0x00 前言
RxJava
现在在各个项目中应用非常广泛,但使用不当很容易出现内存泄漏的风险。如今市面也有很多类似可以避免内存泄漏的RxJava
相关库。例如Uber
开源的AutoDispose
本文的实现也参考了 AutoDispose
的用法,是非侵入式的实现方式。当然还有一些侵入式的实现,不过我认为非侵入式会更好一些。
直接上代码
核心原理是使用Android Lifecycle
接口来实现监听当前页面的显示和销毁的状态,非常简单。
public class AutoDisposable<T> implements ObservableConverter<T, Observable<T>> {
private static final String TAG = "AutoDisposable";
private LifecycleOwner mLifecycleOwner;
private CompositeDisposable mDisposable = new CompositeDisposable();
public AutoDisposable(@androidx.annotation.NonNull LifecycleOwner owner) {
mLifecycleOwner = owner;
initLifecycle();
}
public AutoDisposable(@androidx.annotation.NonNull View view) {
mLifecycleOwner = new ViewLifecycleOwner(view);
initLifecycle();
}
private void initLifecycle() {
mLifecycleOwner.getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@androidx.annotation.NonNull LifecycleOwner source, @androidx.annotation.NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
Log.d(TAG, "do ON_DESTROY");
mLifecycleOwner.getLifecycle().removeObserver(this);
mLifecycleOwner = null;
if (mDisposable != null) {
mDisposable.dispose();
}
}
}
});
}
@Override
public Observable<T> apply(@NonNull Observable<T> upstream) {
return upstream.filter(this::canCallback).doOnSubscribe(disposable -> {
if (mDisposable != null) {
mDisposable.add(disposable);
Log.d(TAG, "doOnSubscribe:" + mDisposable.size());
}
});
}
private boolean canCallback(T t) {
if (mLifecycleOwner == null || mDisposable == null) {
Log.d(TAG, "canCallback >> lifecycleOwner or disposable is null");
return false;
}
if (mDisposable.isDisposed()) {
Log.d(TAG, "canCallback >> isDisposed");
return false;
}
if (mLifecycleOwner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
Log.d(TAG, "canCallback >> DESTROYED");
return false;
}
return true;
}
private static class ViewLifecycleOwner implements LifecycleOwner {
private LifecycleRegistry lifecycleRegistry;
private ViewLifecycleOwner(View view) {
lifecycleRegistry = new LifecycleRegistry(this);
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
}
@Override
public void onViewDetachedFromWindow(View v) {
lifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
view.removeOnAttachStateChangeListener(this);
}
});
}
@androidx.annotation.NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
}
0x01 简单用法
在rxjava
中使用as
或者to
可以将一个Observable
对象转化为另外一个Observable
对象,我们使用这两个操作符,就可以很方便的实现rxjava
与生命周期函数进行绑定,从而避免内存泄漏的风险。
1、与View
进行绑定
Observable.interval(10, TimeUnit.MILLISECONDS).as(new AutoDisposable<>(textView)).subscribe(aLong -> {
Log.d("RXJava", "aLong:" + aLong);
});
2、或者在Activity
或Fragment
中,则会与LifeCycle
进行绑定
Observable.interval(10, TimeUnit.MILLISECONDS).as(new AutoDisposable<>(this)).subscribe(aLong -> {
Log.d("RXJava", "aLong:" + aLong);
});