浅析 - Android LiveData

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/biezhihua/article/details/82860975

前言

https://developer.android.com/reference/android/arch/lifecycle/LiveData?hl=zh-cn
https://developer.android.com/topic/libraries/architecture/livedata?hl=zh-cn

LiveData在整个架构体系中起到了桥梁作用,此外LiveData还持有了数据,并做相应的分发。

LiveData与外界也是个被观察者与观察者的关系。

在这里插入图片描述

在观察者模式的基础上,还为其加上了LifecycleObserver,让其感知生命周期变化可以自己解注册观察者,不可感知与可感知分别对应了observerForever()observer()两个方法。

LiveData相关的类不多,但是各个很有趣。

LiveData

上文说过,LiveData中有两种不同的注册观察者的方式,一种是带有生命周期感知的注册方式,另一种是直接注册(需要手动解注册)。

这其中分别对应了LiveData的中的内部类AlwaysActiveObserverLifecycleBoundObserver,这两个为直接继承自ObserverWrapper

ObserverWrapper内部也很简单,对LiveData是否处于激活状态做了处理与封装,当观察者数量mActiveCount首次大于0时且LiveData处于激活状态时,调用onActive();当观察者数量mActiveCount等于0且LiveData不处于激活状态时,调用onInactive()

LifecycleBoundObserver中集成了LifecycleObserver的子类GenericLifecycleObserver,用来对生命周期做出改变,shouldBeActive()方法则判断了当前LifecycleOwner的当前状态至少为STARTED才能变为激活态。

AlwaysActiveObserver则很简单,shouldBeActive()始终返回true

下面分别让看一下带有生命周期与不带有生命周期的使用LiveData的时序图:

observer(owner, observer)

在这里插入图片描述

observerForever(observer)

在这里插入图片描述

这两个路线的逻辑都很简单,这里就不赘述了,最后都在considerNotify()完成了任务分发:

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    ... 
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
   ... 
    observer.mObserver.onChanged((T) mData);
}

MediatorData

该类直接继承自LiveData,除了可以使用LiveData的基础能力外,还具有将多个LiveData组合在一起的能力。任意一个被组合的LiveData发生变化时,MediatorData的观察者都可以收到改变通知。

其中的关键在于Source这个类,它不仅组合持有LiveDataObserver,同时还继承自Observer,这就代表它具有在LiveData数据发生变化时,将通知再次分发的能力。

在这里插入图片描述

Transformations

与上面不同的是,LiveData提供了持有数据和分发的能力,MediatorLiveData则提供了将多个LiveData组合在一起的能力,Transformations虽然是个工具类,但是却提供了转换LiveData的能力。

LiveData类的转换工具类
可以使用工具类在观察者的生命周期中传递信息。除非观察者正在观察返回的LiveData对象,否则不会计算转换。
因为转换是懒惰地计算的,所以与生命周期相关的行为被隐式传递下去,而不需要额外的显式调用或依赖。

这种能力分为两种:

  • 对LiveData传递的数据进行处理转换的能力。例如:本来传递的是 “test”,经过转换可以将其加工成"test+test"。
  • 对LiveData传递的数据进行二次包装让其成为LiveData的能力。 例如:第一个LiveData的传递数据结果为用户名,但是实际上还想根据这个用户名查询用户的详细信息,就可以根据这个LiveData的结果再包装成第二个可以查询详细信息的LiveData。

首先看下其第一个能力:map - 映射
由于MediatorLiveData可以将多个LiveData进行组合,并观察其LiveData的数据变化,这就可以利用其Observer.onChanged()这个抓手,将结果结果数据进行一次处理,再将其分发给result

public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        public void onChanged(@Nullable X x) {
            // 对x数据进行处理(apply) 并对结果进行分发
            result.setValue(func.apply(x));
        }
    });
    return result;
}

再看下第二个能力:switchMap - 转换映射

虽然switchMap内部嵌套了多次,但是可以将其分离为两层:

  • 第一层result.addSource(trigger, ...,该操作理解为是为了获得懒计算的能力,由于LiveData特性决定,只有观察者注册时onChanged才会被调用,那么位于其中func.apply()才会执行计算。
  • 第二层result.addSource(mSource,...,该操作是为了获取经过func.apply得到的LiveData的计算结果,只有得到新的结果,才能再借助result的能力将其分发给观察者。
public static <X, Y> LiveData<Y> switchMap( LiveData<X> trigger, Function<X, LiveData<Y>> func) {
      final MediatorLiveData<Y> result = new MediatorLiveData<>();
      // 为func提供懒惰计算的能力
      result.addSource(trigger, new Observer<X>() {
          LiveData<Y> mSource;
          
          public void onChanged(@Nullable X x) {
              // 对x结果进行映射转换,得到一个新的LiveData
              LiveData<Y> newLiveData = func.apply(x);
              if (mSource == newLiveData) {
                  return;
              }
              if (mSource != null) {
                  result.removeSource(mSource);
              }
              mSource = newLiveData;
              if (mSource != null) {
                  // 将新的LiveData注册到result中
                  result.addSource(mSource, new Observer<Y>() {
                      public void onChanged(@Nullable Y y) {
                          result.setValue(y);
                      }
                  });
              }
          }
      });
      return result;
  }

猜你喜欢

转载自blog.csdn.net/biezhihua/article/details/82860975