RxLifecycle使用和源码分析
RxJava内存泄漏
-
为什么RxJava会发生内存泄漏?
在当前页面用RxJava发布订阅后,如果当期页面finish时,没有及时取消订阅,这会导致Activity或Fragment无法回收,从而发生内存泄漏。
-
RxLifecycle可以通过绑定生命周期的方式,来解决RxJava内存泄漏的问题。
使用
-
首先需要依赖以下两个库,从而实现两种不同的方法
// 依赖以下两个库,会自动引用基础库与Android库 compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.1.0' compile 'com.trello.rxlifecycle2:rxlifecycle-navi:2.1.0'
-
方法一:继承RxAppCompatActivity
public class RxLifecycleActivity 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.bindToLifecycle())方法绑定Activity的生命周期 //可以替换成.compose(this.<Long>bindUntilEvent(ActivityEvent.STOP)) .compose(this.<Long>bindToLifecycle()) .subscribe(...); } }
- 在onStart方法中调用compose进行绑定,则在onStop方法被调用时自动取消绑定,以此类推。
- 使用bindUntilEvent方法参数要注意遵守上一条的规则。
- compose方法要在subscribeOn方法之后调用,否则如果在被观察者中执行了阻塞方法,比如Thread.sleep(),取消订阅后该阻塞方法不会被中断。
-
方法二:继承NaviActivity
public class RxLifecycleNaviActivity extends NaviActivity { //通过LifecycleProvider对象调用bindToLifecycle或者bindUntilEvent方法 private final LifecycleProvider<ActivityEvent> provider = NaviLifecycle.createActivityLifecycleProvider(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rxlifecycle_navi); initData(); } private void initData() { Observable.interval(1, TimeUnit.SECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) //绑定Activity的生命周期 //可替换成.compose(provider.<Long>bindToLifecycle()) .compose(provider.<Long>bindUntilEvent(ActivityEvent.DESTROY)) .subscribe(...); } }
- 使用的是MVP架构,可把LifecycleProvider对象直接传给Presenter层使用。
原理解析
-
RxAppCompatActivity:
public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> { //通过Subject来监听Activity生命周期事件并对外发射 private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create(); @Override @NonNull @CheckResult public final Observable<ActivityEvent> lifecycle() { return lifecycleSubject.hide(); } //返回LifecycleTransformer对象 @Override @NonNull @CheckResult public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) { return RxLifecycle.bindUntilEvent(lifecycleSubject, event); } //返回LifecycleTransformer对象 @Override @NonNull @CheckResult public final <T> LifecycleTransformer<T> bindToLifecycle() { return RxLifecycleAndroid.bindActivity(lifecycleSubject); } //在Activity不同的生命周期,BehaviorSubject对象会发射对应的ActivityEvent @Override @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); lifecycleSubject.onNext(ActivityEvent.CREATE); } @Override @CallSuper protected void onStart() { super.onStart(); lifecycleSubject.onNext(ActivityEvent.START); } @Override @CallSuper protected void onResume() { super.onResume(); lifecycleSubject.onNext(ActivityEvent.RESUME); } @Override @CallSuper protected void onPause() { lifecycleSubject.onNext(ActivityEvent.PAUSE); super.onPause(); } @Override @CallSuper protected void onStop() { lifecycleSubject.onNext(ActivityEvent.STOP); super.onStop(); } @Override @CallSuper protected void onDestroy() { lifecycleSubject.onNext(ActivityEvent.DESTROY); super.onDestroy(); } }
- 可以看到核心两个方法bindToLifecycle和bindUntilEvent都是返回一个LifecycleTransformer对象,那再去了解下LifecycleTransformer。
-
LifecycleTransformer:
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) { return upstream.takeUntil(observable); } //隐藏其余代码,这里只以Observable为例 ... }
- LifecycleTransformer是实现了(Observable、Flowable等)的Transformer接口。
- 以Observable为例,实际上就是通过传入一个Observable序列并存储为成员,然后作为参数给上游的数据源执行takeUntil方法。
- takeUntil操作符: TakeUntil使用一个标志Observable作为参数来判断是否发射数据,当标志Observable没有发射数据时,调用takeUntil操作符的Observable正常发射数据,而一旦标志Observable发射过了数据则后面的数据都会被丢弃。
- 既然通过bindToLifecycle和bindUntilEvent方法返回一个LifecycleTransformer对象,那我们看看compose或得到LifecycleTransformer对象做了什么。
-
compose:
public final <R> Observable<R> compose(ObservableTransformer<? super T, ? extends R> composer) { return wrap(((ObservableTransformer<T, R>) ObjectHelper.requireNonNull(composer, "composer is null")).apply(this)); } //wrap只是把ObservableSource转换成Observable public static <T> Observable<T> wrap(ObservableSource<T> source) { ObjectHelper.requireNonNull(source, "source is null"); if (source instanceof Observable) { return RxJavaPlugins.onAssembly((Observable<T>)source); } return RxJavaPlugins.onAssembly(new ObservableFromUnsafeSource<T>(source)); }
- compose最终执行的是ObservableTransformer的apply方法并把原始Observable通过参数传进去了,执行LifecycleTransformer的apply方法了,实际上就是执行了upstream.takeUntil(observable)。upstream就是原始的Observable,而observable其实就是Activity里面维护的那个BehaviorSubject。
-
bindActivity:
public final <T> LifecycleTransformer<T> bindToLifecycle() { //通过bindActivity方法,返回了LifecycleTransformer return RxLifecycleAndroid.bindActivity(lifecycleSubject); }
- 我们看看bindActivity是怎么返回LifecycleTransformer对象的。
public static <T> LifecycleTransformer<T> bindActivity(@NonNull final Observable<ActivityEvent> lifecycle) { //里面只是简单的调用了bind方法 return bind(lifecycle, ACTIVITY_LIFECYCLE); } //了解下bind方法 public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle, @Nonnull final Function<R, R>correspondingEvents) { //通过takeUntilCorrespondingEvent方法返回一个Observable给bind方法 return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents)); } //了解下takeUntilCorrespondingEvent方法 private static <R> Observable<Boolean> takeUntilCorrespondingEvent(final Observable<R> lifecycle, final Function<R, R> correspondingEvents) { //接下来一步步解析看看下面做了什么骚操作 return Observable.combineLatest( lifecycle.take(1).map(correspondingEvents), lifecycle.skip(1), new BiFunction<R, R, Boolean>() { @Override public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception { return lifecycleEvent.equals(bindUntilEvent); } }) .onErrorReturn(Functions.RESUME_FUNCTION) .filter(Functions.SHOULD_COMPLETE); }
-
combineLatest 操作符用来将多个Observable发射的数据组装起来然后在发射。
-
lifecycle.take(1)指的是获取发射事件的前一个,如果是take(3)就是获取前三个事件。比如在onCreate()中执行了bindToLifecycle,那么lifecycle.take(1)指的就是ActivityEvent.CREATE。
-
而map(correspondingEvents)中的参数就是ACTIVITY_LIFECYCLE
private static final Function<ActivityEvent, ActivityEvent> ACTIVITY_LIFECYCLE = new Function<ActivityEvent, ActivityEvent>() { @Override 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"); } } };
- 这个方法就是通过调用的bindToLifecycle的生命周期而获取到的事件,来获得到要取消绑定的生命周期事件。比如onCreate()中执行了bindToLifecycle,那么ActivityEvent.CREATE能获取到ActivityEvent.DESTROY,就是要在onDestry方法中取消订阅。
-
第二个参数lifecycle.skip(1)就是除去第一个事件保留剩下的事件。以ActivityEvent.Create为例,这里就剩下:
ActivityEvent.START
ActivityEvent.RESUME
ActivityEvent.PAUSE
ActivityEvent.STOP
ActivityEvent.DESTROY -
第三个参数就是拿第一个参数获取到的事件和第二个参数获取到的事件集合进行比对从而获取到新的序列,比如通过上面的就能得到:
false,false,fasle,false,true
当Activity运行到为false的生命周期时是不会取消订阅的,当运行到true的生命周期就取消订阅。
-
onErrorReturn是对异常的处理
-
filter是对要发送的事件进行筛选,这里只有当运行到需要取消订阅的生命周期才会发送事件,因为发送了事件就就导致之前介绍的takeUntil操作符发挥作用,从而实现取消订阅。
原理总结
- 原始的Observable通过takeUntil和BehaviorSubject绑定,当BehaviorSubject发出数据即Activity的生命周期走到和指定销毁的事件一样时,原始的Observable就终止发射数据了。
参考
- 感谢以下文章作者的努力: