Rxjava解除订阅三部曲:
Rxjava解除订阅①:自带方式和RxLifeCycle
Rxjava解除订阅②:AutoDispose
Rxjava解除订阅③:RxLife
前言
- Rxjava解除订阅①:自带方式和RxLifeCycle
- Rxjava解除订阅②:AutoDispose
本篇RxLife是国人封装的库,我看着也挺好,比较符合国人的使用习惯,实现原理跟AutoDispose很相似,源码也易读,不像老外们写的那么饶,所以也给大家们分析下。
使用
官方介绍RxLife很厉害:
RxLife,相较于trello/RxLifecycle、uber/AutoDispose,具有如下优势:
- 直接支持在主线程回调
- 支持在子线程订阅观察者
- 简单易用,学习成本低
- 性能更优,在实现上更加简单
按照官方文档一步一步来就行,先集成maven:
dependencies {
//rxjava2
implementation 'com.ljx.rxlife2:rxlife-rxjava:2.0.0'
//rxjava3
implementation 'com.ljx.rxlife3:rxlife-rxjava:3.0.0'
}
注:由于Google在19年就停止了非AndroidX的库的更新,故rxlife仅支持AndroidX项目,请尽快将项目迁移至AndroidX
1.Activity/Fragment:
Activity/Fragment销毁时,自动关闭RxJava管道:
Observable.timer(5, TimeUnit.SECONDS)
.as(RxLife.as(this)) //此时的this Activity/Fragment对象
.subscribe(aLong -> {
Log.e("LJX", "accept =" + aLong);
});
2.View
View被移除时,自动关闭RxJava管道
Observable.timer(5, TimeUnit.SECONDS)
.as(RxLife.as(this)) //此时的this 为View对象
.subscribe(aLong -> {
Log.e("LJX", "accept =" + aLong);
});
3.ViewModel
Activity/Fragment销毁时,自动关闭RxJava管道,ViewModel需要继承ScopeViewModel类,如下
public class MyViewModel extends ScopeViewModel {
public MyViewModel(@NonNull Application application) {
super(application);
}
public void test(){
Observable.interval(1, 1, TimeUnit.SECONDS)
.as(RxLife.asOnMain(this)) //继承ScopeViewModel后,就可以直接传this
.subscribe(aLong -> {
Log.e("LJX", "MyViewModel aLong=" + aLong);
});
}
}
注意:一定要在Activity/Fragment通过以下方式获取ViewModel对象,否则RxLife接收不到生命周期的回调
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
4.任意类
Activity/Fragment销毁时,自动关闭RxJava管道,任意类需要继承BaseScope
类,如P层:
public class Presenter extends BaseScope {
public Presenter(LifecycleOwner owner) {
super(owner); //添加生命周期监听
}
public void test(){
Observable.interval(1, 1, TimeUnit.SECONDS)
.as(RxLife.as(this)) //继承BaseScope后,就可以直接传this
.subscribe(aLong -> {
Log.e("LJX", "accept aLong=" + aLong);
});
}
}
5.kotlin用户
由于as是kotlin中的一个关键字,所以在kotlin中,我们并不能直接使用as(RxLife.as(this)),可以如下编写
Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
.`as`(RxLife.`as`(this))
.subscribe { aLong ->
Log.e("LJX", "accept=" + aLong)
}
当然,相信没多少人会喜欢这种写法,故,RxLife针对kotlin用户,新增更为便捷的写法,如下:
Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
.life(this)
.subscribe { aLong ->
Log.e("LJX", "accept=" + aLong)
}
使用life 操作符替代as操作符即可,其它均一样
6.小彩蛋 asOnMain操作符
RxLife还提供了asOnMain
操作符,它可以指定下游的观察者在主线程中回调,如下:
Observable.timer(5, TimeUnit.SECONDS)
.as(RxLife.asOnMain(this))
.subscribe(aLong -> {
//在主线程回调
Log.e("LJX", "accept =" + aLong);
});
//等价于
Observable.timer(5, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.as(RxLife.as(this))
.subscribe(aLong -> {
//在主线程回调
Log.e("LJX", "accept =" + aLong);
});
kotlin 用户使用lifeOnMain替代asOnMain操作符,其它均一样。
注意: RxLife类里面as操作符,皆适用于Flowable、ParallelFlowable、Observable、Single、Maybe、Completable这6个被观察者对象
7.混淆
RxLife作为开源库,可混淆,也可不混淆,如果不希望被混淆,请在proguard-rules.pro文件添加以下代码:
-keep class com.rxjava.rxlife.**{*;}
以上这些全部是官方文档,我只是搬运过来。从上述看来,RxLife是基于google的jetpack
开发的,仅支持androidx及以上版本,不向下兼容。对于现有的商业应用来说,随意升级target是很危险的事情,从而也限制了RxLife的使用场景。
源码解析
- 1.Activity/Fragment
public static RxConverter as(LifecycleOwner owner) {
return as(owner, Event.ON_DESTROY, false);
}
public static RxConverter as(LifecycleOwner owner, Event event) {
return as(owner, event, false);
}
public static RxConverter asOnMain(LifecycleOwner owner) {
return as(owner, Event.ON_DESTROY, true);
}
//上面三个方法 最终调用的此方法
private static RxConverter as(LifecycleOwner owner, Event event, boolean onMain) {
return as(LifecycleScope.from(owner, event), onMain);
}
同AutoDispose一样基于LifecycleOwner
实现生命周期监控。
跟RxLifeCycle和AutoDispose一样,RxLife可以自动识别生命周期,也可以指定生命周期解绑。但跟他们不同的是,所谓自动解绑,是指定在Event.ON_DESTROY
的生命周期解除绑定,可以说是没有RxLifeCycle和AutoDispose那么智能。
而as
和asMain
的区别只是最后一个参数不同,不难猜测,底层肯定是主动切到了主线程。
继续追踪as
方法可以看到这个核心方法:
private void subscribeActual(Observer super T> observer) {
Observable upStream = this.upStream;
if (onMain) {
upStream = upStream.observeOn(AndroidSchedulers.mainThread());
}
upStream.onTerminateDetach().subscribe(new LifeObserver<>(observer, scope));
}
果然是调用了 upStream.observeOn(AndroidSchedulers.mainThread());
切了线程。
那么解绑绑定的核心方法就是LifecycleScope.from(owner, event)
,继续追踪下去:
static LifecycleScope from(LifecycleOwner owner, Event event) {
return new LifecycleScope(owner.getLifecycle(), event);
}
LifecycleScope
实现了LifecycleEventObserver
接口,重写了onStateChanged
方法:
@Override
public void onStateChanged(@NotNull LifecycleOwner source, Event event) {
if (event.equals(this.event)) {
disposable.dispose();
source.getLifecycle().removeObserver(this);
}
}
此为核心代码,很简单的机制,当生命周期改变时会回调这个方法,并与设置的生命周期事件判断,如果一致则dispose
,并将此监听移除。
有removeObserver那肯定也有addObserver,LifecycleScope
还实现了自己写的Scope
:
@Override
public void onScopeStart(Disposable d) {
this.disposable = d;
onScopeEnd();
final Lifecycle lifecycle = this.lifecycle;
if (lifecycle == null)
throw new NullPointerException("lifecycle is null");
lifecycle.addObserver(this);
}
@Override
public void onScopeEnd() {
final Lifecycle lifecycle = this.lifecycle;
if (lifecycle == null)
throw new NullPointerException("lifecycle is null");
lifecycle.removeObserver(this);
}
向上追踪发现AbstractLifecycle
的addObserverOnMain
调用onScopeStart
方法,并且addObserver
调用addObserverOnMain
:
/**
* 事件订阅时调用此方法
*/
protected final void addObserver() throws Exception {
//Lifecycle添加监听器需要在主线程执行
if (isMainThread() || !(scope instanceof LifecycleScope)) {
addObserverOnMain();
} else {
final Object object = mObject;
AndroidSchedulers.mainThread().scheduleDirect(() -> {
addObserverOnMain();
...
});
...
}
}
还是看不出来啥时候add的,继续向上追踪,发现在LifeObserver
中onSubscribe
调用了此方法:
final class LifeObserver extends AbstractLifecycle implements Observer {
@Override
public void onSubscribe(Disposable d) {
if (DisposableHelper.setOnce(this, d)) {
try {
addObserver();
downstream.onSubscribe(d);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
d.dispose();
onError(ex);
}
}
}
细心的朋友们可能已经察觉到了,LifeObserver
就是刚刚我们追踪as
方法时出现过:
private void subscribeActual(Observer super T> observer) {
Observable upStream = this.upStream;
if (onMain) {
upStream = upStream.observeOn(AndroidSchedulers.mainThread());
}
upStream.onTerminateDetach().subscribe(new LifeObserver<>(observer, scope));
}
至此全部逻辑就连在了一起。
- 2.View
自定义View的自动解绑的原理跟Activity和Fragment基本一致,唯一不同的是解绑时机。
ViewScope
实现的OnAttachStateChangeListener
接口,在onViewDetachedFromWindow
方法中实现解除绑定。
@Override
public void onViewDetachedFromWindow(View v) {
disposable.dispose();
v.removeOnAttachStateChangeListener(this);
}
注册监听的地方跟Activity和Fragment一样,也是在onScopeStart。
- 3.任意页面
按照官方文档描述,只要继承BaseScope
就可以实现自动解绑,但实际操作中并不是所谓的只要继承就行。
public class BaseScope implements Scope, LifecycleEventObserver {
public BaseScope(LifecycleOwner owner) {
owner.getLifecycle().addObserver(this);
}
}
事实上构造器得传递LifecycleOwner
,那为什么官方文档上要说任意类呢,原因就像之前提到的RxLife是基于Google的jetpack
来实现的,对应jetpack
来说,ViewModel,LifeCycle等都有自己的生命周期,而且也都与LifecycleOwner
有关,在这几个控件里自定义的组件,的确可以说是任意类。
结语
RxLife相比RxLifeCycle和AutoDispose来说,有着他自己的优势:轻量级,易用,易读,基于jetpack。缺点也很明显,只支持Androidx及以上版本,不向下兼容。项目迁移到Android X涉及到方方面面的改动,风险很大,对于这些应用来说,只能选择使用RxLifeCycle或者AutoDispose了。但google早以停掉了对Androidx以下的支持,迁移到Androidx也只是时间的问题,到时就是RxLife大放光彩的时候了。