深入理解AAC架构 - LiveData 使用以及整体机制源码


LiveData的主要工作:

一个带有生命周期侦测特性的数据持有者。
AAC架构中的实际数据持有者,通常存放在ViewModel中,通过ViewModel脱离生命周期对数据的影响。
本身机制是观察者模式,在数据更新时,会通知所有已激活 (或根据需求通知未激活) 的观察者最新数据。
由于生命周期侦测的特性,LiveData在添加观察者时,要求观察者附带其生命周期所在的LifecycleOwner

  • 官方链接:https://developer.android.google.cn/topic/libraries/architecture/livedata

LiveData的主要类:

  • LiveData
    核心功能类,抽象类。
    LiveData模块的主体,模块的基本实现都在该类中。

  • MutableLiveData
    核心功能类
    LiveData的非抽象子类,只是把postValue()setValue()的访问权限扩大成public并可实例化。

  • Observer
    核心功能类,观察者接口。

  • LiveData$ObserverWrapper
    LiveData的内部类,观察者实例的容器类的抽象父类。
    注册到LiveData的观察者,被会ObserverWrapper的子类包装,再加入观察者列表。
    维护了对应观察者的:
    1- 当前数据版本
    2- 当前观察者的激活状态
    同时负责通知LiveDataonActive()onInactive()

  • LiveData$AlwaysActiveObserver
    ObserverWrapper的一个子类。
    通过LiveData.observeForever()传入的观察者将会被此类包装。
    被该类包装的观察者不关注生命周期,不受生命周期影响,并且激活状态永久为true
    使用该方法时应该注意手动释放观察者,以避免内存泄漏。

  • LiveData$LifecycleBoundObserver
    核心功能类ObserverWrapper的一个子类。
    通过LiveData.observe()传入的观察者将会被此类包装。
    该类是LiveData生命周期监管的核心,该类实现了LifecycleEventObserver接口,并在创建后注册到观察者对应的生命周期内,以实现激活状态管理和主动释放。

  • MediatorLiveData
    MutableLiveData的一个子类。
    该类除了LiveData的功能外,允许对多个LiveData的进行观察。
    简单的描述:
    MutableLiveData会把需要观察的LiveData和对应的Observer封装为一个Source,自身则维护着Source列表。
    MutableLiveData激活时,遍历Source列表,以AlwaysActiveObserver的形式对需要观察的LiveData进行注册。
    MutableLiveData失去激活时,则自动移除Source列表中所有LiveData注册。
    任意LiveData数据更新时,根据需求,决定是否对自身进行维护或更新,即实现了对任意个LiveData的数据更新事件进行管理。

  • Transformations
    工具类,不可实例化。
    用于实现LiveData的数据进行一定的流处理操作,例如发布控制,类型转换等。
    工具类的方法,实际上是通过MediatorLiveData对传入的LiveData进行观察,当LiveData更新数据时,数据会传入的用户定义的方法中进行控制或转换,然后选择性通过MediatorLiveData.setValue()发布处理后的数据。
    工具提供了3个方法:(livedata-2.2.0)
    1- map
    使LiveData通过Function转换为LiveData
    即:LiveData数据更新 - > Function转换 -> MediatorLiveData数据更新
    ..
    2- switchMap
    根据LiveData的数据,根据Function返回需要观察的LiveData
    即:LiveData数据更新 - > Function选择数据源 -> MediatorLiveData数据源更新。
    ..
    map对比,map的数据源直接来自LiveData
    switchMap的数据源是Function返回的LiveDataLiveData对于switchMap来说只是个数据源控制器。
    ..
    3- distinctUntilChanged
    屏蔽LiveData的重复数据发射。
    即:LiveDatasetValue被调用后,将会检测数据是否变更 ( 通过equals() ) ,未发生变更时,将会屏蔽本次更新。

  • ComputableLiveData
    一个未公开的类。(livedata-2.2.0)
    并非LiveData的子类,而是内部维护了一个LiveData
    该类内部LiveData的数据来源,并不来自数据的设置,而是来自子类实现的compute()方法的返回值。当数据更新时,调用invalidate()方法通知LiveData重新调用compute()计算数据。默认运行在一个大小为4,专用IO操作的线程池(arch_disk_io_%i)。


LiveData的基本使用

  • 一般使用:
class VM : ViewModel() {
    val dataSource = MutableLiveData()
}

fun simple(vmOwner: ViewModelStoreOwner, lcOwner: LifecycleOwner) {
    val vm = ViewModelProvider(vmOwner).get(VM::class.java)
    vm.dataSource.observe(lcOwner, Observer { })
}
  • 合并观察:
class VM : ViewModel() {
    val intSource = MutableLiveData()
    val dataSource = MutableLiveData()
}

fun simple(vmOwner: ViewModelStoreOwner, lcOwner: LifecycleOwner) {
    val vm = ViewModelProvider(vmOwner).get(VM::class.java)
    mediator.addSource(vm.intSource) { mediator.value = it.toString() }
    mediator.addSource(vm.dataSource) { mediator.value = it }
}
  • 类型装换:
fun simple() {
    val source: LiveData = MutableLiveData()
    val transfor: LiveData = Transformations.map(source) {
        it.toString()
    }
}
  • 数据源控制
class VMCtrl : ViewModel() {
    private val stateSource = MutableLiveData()
    private val dataSource1 = MutableLiveData()
    private val dataSource2 = MutableLiveData()
    
    // stateSource 数据变更时会导致 outputSource 的数据源变更
    // 从而使 outputSource 数据发生变更
    val outputSource = Transformations.switchMap(stateSource) {
        if (it > 0) {
            dataSource1
        } else {
            dataSource2
        }
    }
}
  • 重复事件屏蔽
class VMUntilChanged : ViewModel() {
    private val source = MutableLiveData()
    // source 设置同一数值,无论多少次,outputSource 只会触发一次数据更新
    val outputSource = Transformations.distinctUntilChanged(stateSource)
}
  • 单次事件发射:
    android/architecture-samples - SingleLiveEvent.java

  • 事件总线:
    深入理解AAC架构 - LiveDataBus 基于LiveData实现的事件总线


LiveData的关键源码分析

  • LiveData的源码并不复杂,先从构造方法进行分析:

在构造方法中就可以直接看到LiveData的两个关键成员
1- mData:当前LiveData保存的数据。
2- mVersion:当前mData的版本,默认-1,通过设置数据的构造方法实例化时,版本为0。

static final Object NOT_SET = new Object();
static final int START_VERSION = -1;

public LiveData() {
    mData = NOT_SET;
    mVersion = START_VERSION;
}

public LiveData(T value) {
    mData = value;
    mVersion = START_VERSION + 1;
}

  • LiveData.observe()作为入口分析:
  1. mObservers
    LiveData的观察者列表,可以看到实际对象是ObserverWrapper类型,即所有传入的observer都会被ObserverWrapper及其子类封装。
  2. assertMainThread()
    该处将会检测是否在主线程调用,否则抛出异常。
  3. LifecycleBoundObserver
    ObserverWrapper子类,观察者的生命周期管理在此处实现。
  4. existing.isAttachedTo(owner)
    观察者不允许绑定多个生命周期,否则抛出异常。
    同一个LiveData中,观察者不能同时 持有 / 忽略 生命周期特性,两者互斥。
  5. addObserver(wrapper)
    LifecycleBoundObserver加入对应生命周期回调以实现自动生命周期管理
private SafeIterableMap, ObserverWrapper> mObservers = new SafeIterableMap<>();

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    assertMainThread("observe");
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }

    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);
}

  • 在分析LifecycleBoundObserver前,先对其父类ObserverWrapper进行分析:
  1. mObserver
    在构造方法中传入的观察者实体,即用户构建的观察者。
  2. mActive
    当前观察者的激活状态,非激活状态时将不会触发观察者的回调。
  3. mLastVersion
    当前观察者对应的数据版本。
  4. shouldBeActive()
    判断观察者是否需要激活,由子类实现。
  5. isAttachedTo()
    判断观察者是否绑定了生命周期,由子类实现,默认为false
  6. detachObserver()
    观察者从LiveData移除时,LiveData会调用观察者包装对象的该方法,以处理必要的释放操作。
  7. activeStateChanged()
    观察者的激活状态通过该方法作出改变。
private abstract class ObserverWrapper {
    final Observer mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }

        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }
        if (mActive) {
            dispatchingValue(this);
        }
    }
}
  • 其中第7activeStateChanged()在状态改变时,有如下性质:
  1. LiveData没有任何已激活的观察者,且此观察者激活,会回调LiveDataonActive()方法
  2. 此观察者取消激活后,LiveData没有任何已激活的观察者,会回调LiveDataonInactive()方法
  3. 观察者激活时,会通过dispatchingValue()通知LiveData尝试派发数据到观察者。

  • 关键方法dispatchingValue()

该方法实际上LiveDatamObservers列表遍历进行通知尝试的方法。
当指定观察者时,尝试对该观察者派发数据;当未指定具体的观察者时,将会遍历整个mObservers列表,对所有观察者派发数据。

  • dispatchingValue()的具体的流程:

当前正在执行派发时,标记当次派发失效,在while循环处重新派发;
指定派发目标时,只对该目标进行派发;
未指定派发目标时,遍历mObservers,对所有观察者进行派发,派发期间检查失效标记,失效时,跳出当次遍历,在while循环处重新派发。

  1. mDispatchingValue:用于标记是否真正派发数据。
  2. mDispatchInvalidated:用于标记当前派发是否失效。
  3. considerNotify():观察者在该方法中根据条件判断是否进行派分数据。
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;

void dispatchingValue(ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }

    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator, ObserverWrapper>> iterator =
                mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

  • 实际的派发方法considerNotify()

该方法比较简单,主要是就是对观察者进行激活和版本校验。
通过校验后,记录最新版本,并推送最新数据到观察者。

  1. !observer.mActive:当观察者未激活时,不执行派发。
  2. observer.shouldBeActive():重复检查观察者是否应该处于激活状态,检查失败则通知观察者取消激活。
  3. observer.mLastVersion >= mVersion:对比观察者版本,仅在版本低于LiveData版本时,通知观察者更新。
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }

    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}
  • 以上即可知道整个派发流程,即通过dispatchingValue()发起,considerNotify()校验,最终派发到观察者。

  • 回头分析LifecycleBoundObserver

前文提到,LifecycleBoundObserverLiveData.observe()时,即绑定到观察者所指定的生命周期中,而绑定通过owner.getLifecycle().addObserver()传入自身作为对象,即LifecycleBoundObserver必然实现LifecycleObserver

  1. mOwner:在构造方法中要求传入生命周期对象。
  2. shouldBeActive():当处于生命周期处于Start - Stop之间时,观察者激活。
  3. onStateChanged():生命周期回调。
    非Destory状态,通过activeStateChanged(shouldBeActive())进行自我状态校验和处理。
    当处于Destory时,通知LiveData移除观察者,LiveData会把包装类从mObservers列表中移除,且触发其detachObserver()方法。
  4. isAttachedTo():直接判断生命周期对象是否相同。
  5. detachObserver():将自身从生命周期中移除,完成整个解绑过程。
class LifecycleBoundObserver 
          extends ObserverWrapper 
          implements LifecycleEventObserver {

    final LifecycleOwner mOwner;

    LifecycleBoundObserver(LifecycleOwner owner, Observer observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle()
                        .getCurrentState()
                        .isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}
  • 通过LifecycleBoundObserver,即LiveData.observe()加入的观察者,实现了生命周期侦测,完成激活状态管理和自动解绑操作。

  • 数据更新:

数据更新有2个方法,且都比较简单,这里不贴出源码。

  1. setValue()
    只能在主线程执行,非主线程调用抛出异常。
    mVersion+1,mData设置为传入数据,并通过dispatchingValue(null)通知所有观察者数据数据更新。
    注意数据设置时,不会进行任何的对比和校验。即设置相同数据时,同样视为更新数据。·

  2. postValue()
    在任意线程中调用,传入的数据会暂存为mPendingData,最终会通过在主线程中调用setValue(mPendingData)进行数据更新。
    注意的是,postValue()被多次调用时,暂存数据mPendingData会被postValue()传入的数据覆盖,最终数据为最后一次的数据。而postValue()发起的主线程任务,在执行到前,只会存在一个任务。即:
    多次postValue()调用,在真正主线程执行前,共享同一次任务。而其中的暂存数据mPendingData会被覆盖为最后一次postValue()的传入值。
    使用postValue()应该注意该问题,极短时间内多次postValue()设置数据,会可能导致数据更新丢失。


  • LiveData.observeForever()

添加忽略生命周期侦测特性的观察者。
通过该方法加入的观察者不需要传入生命周期参数,即忽略生命周期侦测。
所以使用该方法时需要注意,在合适的时候调用removeObserver()移除观察,避免发生内存泄漏。

  1. 通过observeForever()传入的观察者,将会被包装为AlwaysActiveObserver,该包装类的shouldBeActive()方法估计返回true,即任何数据更新都会通知到该观察者。
  2. 同一个LiveData中,观察者不能同时 持有 / 忽略 生命周期特性,两者互斥。
  3. 新加入的观察者,在方法的最后都会通过activeStateChanged(true)通知LiveData更新数据到观察者。
public void observeForever(Observer observer) {
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    wrapper.activeStateChanged(true);
}

  • 观察者移除:

观察者移除有2个方法,且都比较简单,这里不贴出源码。

  1. removeObserver(Observer observer)
    该方法用于移除指定的观察者,如果绑定生命周期,则会解除绑定。
  2. removeObservers(LifecycleOwner owner)
    仅针对通过LiveData.observe()添加,绑定了生命周期的观察者,移除维护中的所有生命周期对象为传入对象的观察者。最终也是通过removeObserver()逐一移除。

你可能感兴趣的:(深入理解AAC架构 - LiveData 使用以及整体机制源码)