调用链的生成
以fragment为例,fragment继承RxLifecycle的RxFragment,然后在fragment中发起网络请求
// Retrofit生成的observable
Retrofit.create(xxx).subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(fragment.bindUntilEvent(FragmentEvent.DETACH))
.subscribe(new Observer<Response<T>>() {
@Override
public void onError(Throwable e) {
onResponseError(e);
}
@Override
public void onComplete() {
// do something
}
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Response<T> t) {
onResponse(t);
}
});
生成的调用链如下
this = {ObservableTakeUntil@14202}
other = {ObservableFilter@14199}
predicate = {RxLifecycle$1@14208}
event = {FragmentEvent@14227} "DETACH"
source = {BehaviorSubject@14209}
source = {ObservableObserveOn@14193}
scheduler = {HandlerScheduler@14188}
source = {ObservableUnsubscribeOn@14187}
scheduler = {IoScheduler@14181}
source = {ObservableSubscribeOn@14180}
scheduler = {IoScheduler@14181}
source = {CallExecuteObservable@14166}
关键方法的调用
根据生成的调用链,最后调用的subscribe就是ObservableTakeUntil.subscribe()方法,它的subscribeActual()方法如下
@Override
public void subscribeActual(Observer<? super T> child) {
final SerializedObserver<T> serial = new SerializedObserver<T>(child);
final ArrayCompositeDisposable frc = new ArrayCompositeDisposable(2);
final TakeUntilObserver<T> tus = new TakeUntilObserver<T>(serial, frc);
child.onSubscribe(frc);
other.subscribe(new TakeUntil(frc, serial));
source.subscribe(tus);
}
这里的other是ObservableFilter,source是ObservableObserveOn,在other/source.subscribe()的调用中,通过调用链,会分别在BehaviorSubject/ObservableSubscribeOn.subscribeActual()中调用onSubscribe(),最终会调用到TakeUntil/TakeUntilObserver.onSubscribe(),在这里,会对frc赋值,赋值后,frc如下
this = {ArrayCompositeDisposable@6850}
array = {Object[2]@6871}
0 = {ObservableObserveOn$ObserveOnObserver@6862} "0"
1 = {ObservableFilter$FilterObserver@6852}
dispose的调用
有两条路径会调用到dispose
ObservableTakeUntil.subscribeActual
ObservableFilter.subscribeActual
BehaviorSubject.subscribeActual
BehaviorSubject$BehaviorDisposable.emitFirst
// 这以后是真正的dispose流程
BehaviorSubject$BehaviorDisposable.test
NotificationLite.accept
ObservableFilter$FilterObserver.onNext
ObservableTakeUntil$TakeUntil.onNext // 这里在调用dipose的同时还调用了onCompete,通知到observer
ArrayCompositeDisposable.dispose
// 这里遍历frc并进行dispose
ObservableObserveOn$ObserveOnObserver.dispose
ObservableUnsubscribeOn$UnsubscribeObserver.dispose // 设置AtomicBoolean标识为true,表示已经dispose
ObservableSubscribeOn$SubscribeOnObserver.dispose
DisposableHelper.dispose
CallExecuteObservable.dispose // 调用okHttpCall.cancel
DisposableHelper.dispose
scheduler.dispose
ObservableFilter$FilterObserver
BasicFuseableObserver.dispose
BehaviorSubject$BehaviorDisposable.dispose // cancel设置为true
Fragment.onDetach
BehaviorSubject.onNext(FragmentEvent.DETACH)
BehaviorSubject$BehaviorDisposable.emitNext
// 这以后是真正的dispose流程,同上
BehaviorSubject$BehaviorDisposable.test
上面不同的observer都进行了dispose,具体的dispose不一样,比如终止okHttpCall,终止scheduler,设置标识位等。
如果:
1. 在发起请求之前就dispose,会走第一个分支,因为okHttpCall已经cancel,所以不会再发起请求
2. 在发起请求之后dispose,会走第二个分支,因为ObservableUnsubscribeOn$UnsubscribeObserver已经dispose,get() == true, 所以这里的onNext不会再进行任何操作,如下
@Override
public void onNext(T t) {
if (!get()) {
actual.onNext(t);
}
}
由于在dispose中终止调用并进行了清理,同时还调用了onComplete,所以不会造成内存泄漏,也不会再回调到Activity/Fragment,造成可能的空指针等异常
总结
关键在两点:
1. 生成了ObservableTakeUntil,里面除了source之外,还生成了other,other根据predicate(条件)来定义behavior(行为),即当predicate.test为true时执行通过behavior调用ObserverFilter
FilterObserver的方法2.ObserverFilter
FilterObserver实际上会再调用ObservableTakeUntil$TakeUntil.onNext,这里就通过frc进行了dispose
Bug:
一个RxLifecycle的小问题。
在compose的时候
1. 如果until事件是FragmentEvent.DESTROY_VIEW,fragment的请求在onDestoryView之后发出,会出现问题。原因:在onDestoryView的时候,因为请求还没有发出,队列是空的,所以BehaviorSubject$BehaviorDisposable.emitNext不会调用到,而之后,DESTROY_VIEW事件被后面的DESTORY和DETACH事件依次冲掉,所以请求返回时由于事件不是DESTROY_VIEW,所以请求不会被取消,最后请求的回调依然被调用
2. 如果until事件是FragmentEvent.DETACH,那么在onDestoryView和onDetach之间返回了请求结果的话也会发生问题。
综合考虑,把until事件设置成DESTROY_VIEW,然后把RxFragment里的onDestory和onDetach中调用的onNext去掉比较好。