参考:
Android技能树 — Rxjava取消订阅小结(2):RxLifeCycle
RxLifeCycle 官方demo:
//Note:Activity需要继承RxAppCompatActivity,fragment需要继承RxFragment
// implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
// // If you want to bind to Android-specific lifecycles
// implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
// // If you want pre-written Activities and Fragments you can subclass as providers
// implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
public class Activity1 extends RxAppCompatActivity { //RxAppCompatActivity
private static final String TAG = "RxLifecycleAndroid";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setContentView(R.layout.activity_main);
// Specifically bind this until onPause()
Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG,
"Unsubscribing subscription from onCreate()");
}
})
//在activity onPause的时候取消订阅 : 【手动】指定结束时间
.compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long num) throws Exception {
Log.i(TAG,
"Started in onCreate(), running until onPause(): " + num);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart()");
// Using automatic unsubscription,
//this should determine that the correct time to
// unsubscribe is onStop (the opposite of onStart).
//使用自动退订,这应该确定//退订的正确时间是onStop(与onStart相反)。
Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG, "Unsubscribing subscription from onStart()");
}
})
//bindToLifecycle的自动取消订阅示例,因为是在onStart的时候调用,
//所以在onStop的时候自动取消订阅
//自动设定解除订阅的时间:
//(ps:比如你是在onStart时候订阅,则自动会在onPause时候解除,
//如果在onCreate时候订阅,则会自动在onDestory时候解除)
//【自动】识别结束时间: 根据当前的生命周期
.compose(this.<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long num) throws Exception {
Log.i(TAG,
"Started in onStart(), running until in onStop(): " + num);
}
});
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
// `this.<Long>` is necessary if you're compiling on JDK7 or below.
//
// If you're using JDK8+, then you can safely remove it.
Disposable disposable = Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG,
"Unsubscribing subscription from onResume()");
}
})
//在activity onDestroy的时候取消订阅 ,【手动】指定结束时间
.compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long num) throws Exception {
Log.i(TAG, "Started in onResume(),
running until in onDestroy(): " + num);
}
});
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause()");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
}
}
RxAppCompatActivity 源码
public abstract class RxAppCompatActivity extends AppCompatActivity
implements LifecycleProvider<ActivityEvent> {
//创建一个BehaviorSubject,用来做takeUntil中的第二个Observable,
//让其在核实的生命周期发送信息。
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();
//使用hide()方法把这个subject暴露出去
}
@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);
}
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在onCreate时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@CallSuper
protected void onStart() {
super.onStart();
//在onStart时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.START);
}
@CallSuper
protected void onResume() {
super.onResume();
//在onResume时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.RESUME);
}
@CallSuper
protected void onPause() {
//在onPause时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.PAUSE);
super.onPause();
}
@CallSuper
protected void onStop() {
//在onStop时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.STOP);
super.onStop();
}
@CallSuper
protected void onDestroy() {
//在onDestroy时候发送信息
this.lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}
注意:
在onCreate , onStart , onResume的时候,都是先调用super.XXX, 然后再用subject 发送相关Event;
但是在 onPause , onStop , onDestory 里面却是先用subject 发送相关Event,然后再调用super.XXXX。
为啥会有这个区别。
因为一般取消订阅都是在onPause,onStop,onDestory情形下,所以优先先取消订阅,再去执行系统自己的操作。
比如onDestory,先去取消订阅,再去执行super.onDestory方法。
手动解除订阅
手动解除订阅会调用 bindUntilEvent 等一系列方法:
//将给定的源绑定到生命周期。 当生命周期事件发生时,源将停止发出任何通知。
//lifecycle : 生命周期序列
//event : 应该终止来自源的通知的事件
public static <T, R> LifecycleTransformer<T> bindUntilEvent(
@Nonnull final Observable<R> lifecycle,
@Nonnull final R event) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(event, "event == null");
return bind(takeUntilEvent(lifecycle, event));
}
//只监听指定的生命周期
private static <R> Observable<R> takeUntilEvent(
final Observable<R> lifecycle, final R event) {
return lifecycle.filter(new Predicate<R>() {
@Override
public boolean test(R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(event);
}
});
}
//将给定的源绑定到生命周期。
//此帮助程序会自动(根据生命周期序列本身)确定源应该何时停止发射物品。
//请注意,对于此方法,它假定给定生命周期发出的any事件表示生命周期已结束。
public static <T, R> LifecycleTransformer<T> bind(
@Nonnull final Observable<R> lifecycle) {
return new LifecycleTransformer<>(lifecycle);
}
LifecycleTransformer 实现的apply方法:
//observable : 生命周期
LifecycleTransformer(Observable<?> observable) {
checkNotNull(observable, "observable == null");
this.observable = observable;
}
//upstream : 我们自己的observable
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
//当observable发射数据,upstream就会停止
return upstream.takeUntil(observable);
}
总结:
lifecycleSubject 会发送各个生命周期,并监听指定的生命周期,当到达指定的时间,便通过takeUntil取消我们自己的observable任务
自动解除订阅:
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(this.lifecycleSubject);
}
这里 bindToLifecycle() 实质调用:
RxLifecycleAndroid.bindActivity(this.lifecycleSubject);
public static <T> LifecycleTransformer<T> bindActivity(
@NonNull Observable<ActivityEvent> lifecycle) {
return RxLifecycle.bind(lifecycle, ACTIVITY_LIFECYCLE);
}
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");
}
}
};
这里 bindActivity() 实质调用:
RxLifecycle.bind(lifecycle, ACTIVITY_LIFECYCLE)
//将给定的源绑定到生命周期。
//此方法(根据生命周期序列本身)确定源应该何时停止发射物品。
//它使用提供的相应事件函数确定何时取消订阅。
//请注意,这是该库的高级用法,通常应仅在您真正了解给定生命周期正在做什么时才使用。
//lifecycle : 生命周期序列
//correspondingEvents : 一个Function,告知源何时取消订阅
public static <T, R> LifecycleTransformer<T> bind(
@Nonnull Observable<R> lifecycle,
@Nonnull final Function<R, R> correspondingEvents) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(correspondingEvents, "correspondingEvents == null");
return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
}
这里 bind() 实质调用:
bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents))
private static <R> Observable<Boolean> takeUntilCorrespondingEvent(
final Observable<R> lifecycle,
final Function<R, R> correspondingEvents) {
return Observable.combineLatest(
//第一个Observable:记录在哪个生命周期去取消订阅。
lifecycle.take(1).map(correspondingEvents),
//第二个Observable:在不同生命周期发送不同事件,
//当二个事件和第一个事件相同时候就说明要取消订阅了。
//但是我们第一次要跳过,因为第一个事件是在订阅时候发生的 。
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);
}
//这里的bind方法和手动解除订阅是一样的:
public static <T, R> LifecycleTransformer<T> bind(
@Nonnull final Observable<R> lifecycle) {
return new LifecycleTransformer<>(lifecycle);
}
来看Observable.combineLatest,这个操作符接收三个参数。
第一个参数:取BehaviorSubject发射的数据中的第一个,然后转换成对应的生命周期。例如在onStart()中调用了bindToLifecycle,take(1)后的数据是ActivityEvent.START,经过map(),返回ActivityEvent.STOP。
第二个参数:从BehaviorSubject发射的数据中经过.skip(1)操作符,过滤掉第一个数据。例如在onStart()中调用了bindToLifecycle,在后续的生命周期中会收到,ActivityEvent.RESUME、ActivityEvent.PAUSE、ActivityEvent.STOP、ActivityEvent.DESTROY
第三个参数:作用是combineFunction,把前两个参数最近发射的数据按照规则进行合并。规则是比对两次事件是否相等,然后合并后数据返回Boolean结果。比如params2发射ActivityEvent.RESUME的时候,和params1发射的ActivityEvent.STOP进行比对,返回false结果;params2发射ActivityEvent.STOP的时候,和params1发射的ActivityEvent.STOP进行比对,返回true结果。
通过combineLatest把二个绑定一起,这时候就会在指定的生命周期时候就会发送true,其余时候发送false,
最后配合filter操作符,只有在true的时候才能发送即可。
这样最终通过takeUntil再把我们的Observable绑定在一起,
然后这时候这里发送true的时候,我们的Observable就会取消订阅了。