这是一篇关于AutoDispose/RxLifecycle/Google Lifecycle
的详细分析,以做记录。
Architecture Components Lifecycle
Google之前推出过一套Architecture Components
,里面的Lifecycle
组件是LiveData
等的基础组件。
具体的生命周期过程不再介绍。我们来看google官网对整个生命周期流动的解释。
在该Lifecycle
组件中,与传统的生命周期不同,只定义了五种状态,分别是:
- INITIALIZED 最初始的状态
- DESTROYED
- CREATED
- STARTED
- RESUMED
上图中向右的箭头很好理解,每过来一个events会发生生命周期状态的变更
向左的箭头可以看成状态的回滚, 如果在RESUMED
状态发生了onPause()
事件,则状态回滚到RESUMED
之前的STARTED
状态
这幅图是我看完源码后对整个架构的总结。整个组件由三大部分组成:LifecycleRegistry
& LifecycleOwner
& LifecycleObserver
LifecycleOwner
生命周期事件分发者。例如我们最熟悉的Activity/Fragment
。它们在生命周期发生变化时发出相应的Event
给LifecycleRegistry
。
LifecycleObserver
生命周期监听者。通过注解将处理函数与希望监听的Event
绑定,当相应的Event
发生时,LifecycleRegistry
会通知相应的函数进行处理。
LifecycleRegistry
控制中心。它负责控制state
的转换、接受分发event
事件。其实个人觉得Lifecycle
组件与EventBus
很类似? 但以下代码表现了他们的不同:
while (mObserverCurrentState != mState) {
Event event = mObserverCurrentState.isAtLeast(mState)
? downEvent(mObserverCurrentState) : upEvent(mObserverCurrentState);
mObserverCurrentState = getStateAfter(event);
mCallback.onStateChanged(mLifecycleOwner, event);
}
假设现在的状态为RESUMED
,但是observer的状态还在CREATED
,那么就会走upEvent(mObserverCurrentState)
依次向observer发送start&resume
事件。
假设现在的状态为CREATED
,但是observer的状态还在RESUMED
,说明observer状态超前了,那么就会走downEvent(mObserverCurrentState)
依次向observer发送pause&stop
事件。
侵入性问题
Lifecycle
组件为了降低侵入性,首先通过registerActivityLifecycleCallbacks
给每个启动的Activity创建了一个ReportFragment
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(mFragmentCallback, true);
}
// ProcessLifecycleOwner should always correctly work and some activities may not extend
// FragmentActivity from support lib, so we use framework fragments for activities
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
// Hopefully, we are the first to make a transaction.
manager.executePendingTransactions();
}
}
然后在ReportFragment
中真正根据生命周期去触发Activity的Lifeycle事件
。当然我并不明白它为什么不直接用ActivityLifecycleCallback
非要通过Fragment
中转。有知道的朋友解释一下~
RxLifecycle
因为Rxjava2
的流行,顺其自然的出现了RxLifecycle
组件,主要防止Rxjava
的泄漏,在生命周期结束时取消Subscription
为了依旧实现Rxjava
的链式调用,RxLifecycle
很巧妙的使用了TakeUtil
运算符
TakeUtil
看图非常容易理解,不再解释。
LifecycleProvider
与前面类似,Activity
等作为生命周期的提供者LifecycleProvider
,该Provider
会提供一个转换器LifecycleTransformer
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
//当observable发射时停止upstream
return upstream.takeUntil(observable);
}
即经过该转换器的转化,上游事件发生者会被另一个Observable
限制发射。那么这个作为限制的Observable
究竟是什么呢:
observable1
过滤出指定事件,这个可以实现到指定的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);
}
});
}
observable2
//R ActionEvent
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);
}
这个略微复杂,举例来说,如果你在onCreate
中bindLifecycle
,那Rxlifecycle
会自动帮你在onDestroy
里注销。onStart&onStop
同理。所以代码就比较好理解,lifecycle.take(1).map(correspondingEvents)
会找到对应的endEvent
,然后与后续发射的Event
对比,如果两者相等说明已经到了该结束的时刻了!
BehaviorSubject
BehaviorSubject
是观察Lifecycle
事件,在onCreate
的时候它发射create event
。我们把它跟真实的Observable
绑定在一起,实现前面的takeUtil
。当BehaviorSubject
发射特定的事件时,真实的Observable
退出。
// observer will receive the "one", "two" and "three" events, but not "zero"
BehaviorSubject<Object> subject = BehaviorSubject.create();
subject.onNext("zero");
subject.onNext("one");
subject.subscribe(observer);
subject.onNext("two");
subject.onNext("three");
可以看到,上述中observer
只会收到one,two,three
事件。而在RxActivity
中,
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
所以如果在onStart
中绑定lifecycle
事件,BehaviorSubject
会收到从onStart
开始的事件,这是不是跟前面的observable2
结合起来看就一目了然了。
侵入性
Rxlifecycle
具有很强的侵入性。从sample中也可以看到,你需要继承RxActivity
,并且悲剧的是从前面截图可以看到,整篇代码在ide中飘黄,大概因为Rxjava2
强制subscribe后返回的结果需要@CheckReturnValue
。不过这也不能怪Rxlifecycle
..毕竟取消了它的代码也还是会有警告- -
有关MVP
其实我们可以自己改造Rxlifecycle
,我们知道,Presenter
也是有生命周期的。最简单而言attachView() & detachView()
。因此我们可以做如下改造:
//核心代码
@Override
@CallSuper
public void attachView(V view) {
super.attachView(view);
lifecycleSubject.onNext(PresenterEvent.ATTACH);
}
Autodispose
Uber的Autodispose
和Rxjava2
作用类似。但他很巧妙的解决了上面的问题。
当然,他的整体设计也更复杂一些。
ObservableSubscirbeProxy(single..类同)
它解决了Rxjava2
中警告的问题。这里的subscribe
不再是Observable.subscribe
,而是在外面包了一层Subscribeproxy
。简单来说,对于autoDispose
而言,他其实打破了整个Rxjava subscribe to Observer
的链路,而是完全由自己监管。
可以看到,将一个上游事件发射者转变为subscribeProxy
所以最终subscribe(observer)
时,实际发生的是
AutoDisposeObservable<>(observableSource, scope()).subscribe(observer)
这里的observableSource
是上游事件,scope
是Maybe<?>
。我们重点关注scope
是什么:
autoDisposable(deferredResolvedLifecycle(checkNotNull(provider, "provider == null")));
AndroidLifecycleScopeProvider.from(this)
LifecycleEventsObservable
先插一句介绍一下这玩意。
接受Lifecycle
作为参数一般是Activity...
。它的内部有一个ArchLifecycleObserver
,
我们可以把它看成一个发射LifecycleEvent
的事件源。该事件源包含真实的Lifecycle
,当它subscirbe(observer)
时,会Lifecycle.add
将它与lifecycle
绑定起来。当observer
监听到事件时,会调用actualObserver.onNext
。
这边不理解可以先忽略,后面会再回过头来看。
LifecycleScopeProvider
生命周期的提供者。包含上述的LifecycleEventsObservable
关键代码
autoDisposable(deferredResolvedLifecycle(checkNotNull(provider, "provider == null")));
这里的deferredResolvedLifecycle
返回了前面的Maybe<?>:
return Maybe.defer(new Callable<MaybeSource<? extends LifecycleEndNotification>>() {
@Override public MaybeSource<? extends LifecycleEndNotification> call() throws Exception {
E lastEvent = provider.peekLifecycle();
//outsideLifecycle
if (checkStartBoundary && lastEvent == null) {
LifecycleNotStartedException exception = new LifecycleNotStartedException();
Consumer<? super OutsideLifecycleException> handler
= AutoDisposePlugins.getOutsideLifecycleHandler();
if (handler != null) {
handler.accept(exception);
return Maybe.just(LifecycleEndNotification.INSTANCE);
} else {
throw exception;
}
}
E endEvent;
try {
endEvent = provider.correspondingEvents()
.apply(lastEvent);
} catch (Exception e) {
if (checkEndBoundary && e instanceof LifecycleEndedException) {
Consumer<? super OutsideLifecycleException> handler
= AutoDisposePlugins.getOutsideLifecycleHandler();
if (handler != null) {
handler.accept((LifecycleEndedException) e);
return Maybe.just(LifecycleEndNotification.INSTANCE);
} else {
throw e;
}
} else {
return Maybe.error(e);
}
}
return resolveScopeFromLifecycle(provider.lifecycle(), endEvent);
}
});
不懂这里为什么要Maybe.defer
?
这里的lastEvent
指的是上一个事件,endEvent
指的是上一个事件对应的结束事件。。比如Create
对应Destroy
/**
* @param lifecycle the stream of lifecycle events
* @param endEvent the target end event
* @param <E> the lifecycle event type
* @return a resolved {@link Maybe} representation of a given lifecycle, targeting the given event
*/
public static <E> Maybe<LifecycleEndNotification> resolveScopeFromLifecycle(
Observable<E> lifecycle,
final E endEvent) {
return lifecycle.skip(1)
.map(new Function<E, Boolean>() {
@Override public Boolean apply(E e) throws Exception {
return e.equals(endEvent);
}
})
.filter(IDENTITY_BOOLEAN_PREDICATE)
.map(TRANSFORM_TO_END)
.firstElement();
}
这段代码是不是在Rxlifecycle
中似曾相识。。。废话,他也是得到与endEvent
匹配的事件。这里看到provider.lifecycle()
了吗,我们可以回到上面的LifecycleEventsObservable
。当它被订阅的时候,就真正与Activity
这种LifecycleOwner
绑定了起来,当observer
监听到生命周期事件并发生onStateChange
时,会调用actualObserver.onNext
。
扯了一大堆,结论就是scope
返回了一个Observable
,它只会在发生对应的endEvent
时发出事件。
不得不感慨uber工程师设计的精妙。。
那我们再回过头来看最初的代码:
AutoDisposeObservable<>(observableSource, scope()).subscribe(observer)
-->
source.subscribe(new AutoDisposingObserverImpl<>(scope, observer));
AutoDisposingObserverImpl
是一个很 有趣的类,它让scope
被一个DisposableMaybeObserver
订阅,当scope
发出endEvent
事件时,该observer
会把mainDisposable
的状态设置为DISPOSED
,而当真实的observer
收到事件时,如果发现mainDisposable
已经为DISPOSED
就不会处理接受到的真实事件。
我把整个过程过程了一张图,作为总结。
从上图可以看到,LifecycleScopeProvider
包括LifecycleEventsObservable
,后者与endEvent
组合生成了一个叫scope()
的事件发生器。当这个java source.subscribe(new AutoDisposingObserverImpl<>(scope, observer));
发生时,scope
向DisposableMaybeObserver
订阅。
这时如果Lifecycle
发出LifecycleEvent
,因为ArchLifecycleObserver
是一个LifecycleObserver
,他可以监听到生命周期事件。并且传递给下流downStream,经过之前的串联运算符的过滤后到DisposableMaybeObserver
就是真正的endEvent
。可以看到顺理成章完成了我们希望达到的目的。
Why Not RxLifecycle?
挺有趣的,Rxlifecycle原作者写了一篇为什么不要使用rxlifecycle - -
他提出了以下几点原因并给出了自己的优化建议,当然有些个人觉得是他强迫症了- -
- 他认为自动化的生命周期检测有的时候会让人感到困扰,有的时候你的组件可能不在
activity
里面,那你需要把lifecycle
传递给他,并且寄希望于在正确的生命周期时间进行unsubscribe
(这个正确的可能很难做到).比如你有一个adapter
,它的数据来源于observable
.关键在于你无法知道什么时候可以unsubscribe
..因为你在adapter
里没有地方给你生命周期函数去subscribe
....当然你可以使用bindUntilEvent()
,但是就削弱了rxlifecycle
提供的功能 - 经常其实我们还是会手动去处理
subscription
。比如adapter
这个例子,可能我现在正在监听一个数据源,但是之后想监听另一个,那就需要把上一个取消掉。这个时候用户可能会感到很奇怪,为什么我们在一个地方手动ubsubscribe()
同时又在另一个地方用了rxlifecycle
- 还有前面提到过的问题,作者也进行了罗列。
作者还顺便略推荐了一把autodispose
...至于他说的fewer restrictions on when it can be used in a stream
我没怎么看懂。个人觉得可能想表达的是,Rxlifecycle
使用了takeUtil
运算符,直接就侵入了原有的流。而autoDispose
还是完整的保留了原有的流。有知道的麻烦回复一下~
其实Rxlifecycle
之前有较多问题是因为基于rxjava1
,后来他迁到2.x
版本后还是解决了很多问题的,比如也开始支持Single
等等。
最后作者给出了一些优化建议与模式,我们开发可以参考:
- 手动处理
subscription
。其实我们可以看到一种做法,把subscriptions
存储在compositeSubscription
(一个容器)。在合适的时候只要把compositeSubscription
取消即可把全部订阅都取消。 - 对于类似
adapter
的组件,他应该把自己的订阅抛到上层。例如adapter
,就应该把subscription
返回给activity
让他去进行生命周期的管理。 -
kotlin
天然的null
优势,让开发者通过一行代码mySubscription?.unsubscribe()
即可取消订阅
上面三种模式,最终希望达到同一个目的。但我们在使用的时候还是要注重业务场景,例如后两者明显是为Rxjava
量身打造的,而前一种很适合用于单组件,例如前面提到的adapter
,它就不会遇到后两者拥有的问题。
本文完结。有些问题还等待解决。