有关Android Lifecycle的一些事

这是一篇关于AutoDispose/RxLifecycle/Google Lifecycle的详细分析,以做记录。

Architecture Components Lifecycle

Google之前推出过一套Architecture Components,里面的Lifecycle组件是LiveData等的基础组件。

image.png

具体的生命周期过程不再介绍。我们来看google官网对整个生命周期流动的解释。

在该Lifecycle组件中,与传统的生命周期不同,只定义了五种状态,分别是:

  • INITIALIZED 最初始的状态
  • DESTROYED
  • CREATED
  • STARTED
  • RESUMED

上图中向右的箭头很好理解,每过来一个events会发生生命周期状态的变更
向左的箭头可以看成状态的回滚, 如果在RESUMED状态发生了onPause()事件,则状态回滚到RESUMED之前的STARTED状态

image.png

这幅图是我看完源码后对整个架构的总结。整个组件由三大部分组成:LifecycleRegistry & LifecycleOwner & LifecycleObserver

LifecycleOwner

生命周期事件分发者。例如我们最熟悉的Activity/Fragment。它们在生命周期发生变化时发出相应的EventLifecycleRegistry

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

image.png

为了依旧实现Rxjava的链式调用,RxLifecycle很巧妙的使用了TakeUtil运算符

TakeUtil

image.png

看图非常容易理解,不再解释。

LifecycleProvider

与前面类似,Activity等作为生命周期的提供者LifecycleProvider,该Provider会提供一个转换器LifecycleTransformer

image.png
@Override
public ObservableSource apply(Observable upstream) {
    //当observable发射时停止upstream
    return upstream.takeUntil(observable);
}

即经过该转换器的转化,上游事件发生者会被另一个Observable限制发射。那么这个作为限制的Observable究竟是什么呢:

observable1

过滤出指定事件,这个可以实现到指定的Event时取消事件绑定。

private static  Observable takeUntilEvent(final Observable lifecycle, final R event) {
    return lifecycle.filter(new Predicate() {
        @Override
        public boolean test(R lifecycleEvent) throws Exception {
            return lifecycleEvent.equals(event);
        }
    });
}

observable2

//R ActionEvent
private static  Observable takeUntilCorrespondingEvent(final Observable lifecycle,
                                                                   final Function correspondingEvents) {
    return Observable.combineLatest(
        //拿一个
        lifecycle.take(1).map(correspondingEvents),
        lifecycle.skip(1),
        new BiFunction() {
            @Override
            public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
                return lifecycleEvent.equals(bindUntilEvent);
            }
        })
        .onErrorReturn(Functions.RESUME_FUNCTION)
        .filter(Functions.SHOULD_COMPLETE);
}

这个略微复杂,举例来说,如果你在onCreatebindLifecycle,那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 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的AutodisposeRxjava2作用类似。但他很巧妙的解决了上面的问题。

image.png

当然,他的整体设计也更复杂一些。

ObservableSubscirbeProxy(single..类同)

它解决了Rxjava2中警告的问题。这里的subscribe不再是Observable.subscribe,而是在外面包了一层Subscribeproxy。简单来说,对于autoDispose而言,他其实打破了整个Rxjava subscribe to Observer的链路,而是完全由自己监管。

image.png

可以看到,将一个上游事件发射者转变为subscribeProxy

所以最终subscribe(observer)时,实际发生的是

AutoDisposeObservable<>(observableSource, scope()).subscribe(observer)

这里的observableSource是上游事件,scopeMaybe。我们重点关注scope是什么:


autoDisposable(deferredResolvedLifecycle(checkNotNull(provider, "provider == null")));


AndroidLifecycleScopeProvider.from(this)

LifecycleEventsObservable

先插一句介绍一下这玩意。

接受Lifecycle作为参数一般是Activity...。它的内部有一个ArchLifecycleObserver

image.png

我们可以把它看成一个发射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>() {
      @Override public MaybeSource call() throws Exception {
        E lastEvent = provider.peekLifecycle();
        //outsideLifecycle
        if (checkStartBoundary && lastEvent == null) {
          LifecycleNotStartedException exception = new LifecycleNotStartedException();
          Consumer 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 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  the lifecycle event type
   * @return a resolved {@link Maybe} representation of a given lifecycle, targeting the given event
   */
  public static  Maybe resolveScopeFromLifecycle(
      Observable lifecycle,
      final E endEvent) {
    return lifecycle.skip(1)
        .map(new Function() {
          @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));发生时,scopeDisposableMaybeObserver订阅。

这时如果Lifecycle发出LifecycleEvent,因为ArchLifecycleObserver是一个LifecycleObserver,他可以监听到生命周期事件。并且传递给下流downStream,经过之前的串联运算符的过滤后到DisposableMaybeObserver就是真正的endEvent。可以看到顺理成章完成了我们希望达到的目的。

Why Not RxLifecycle?

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,它就不会遇到后两者拥有的问题。

本文完结。有些问题还等待解决。

你可能感兴趣的:(有关Android Lifecycle的一些事)