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- 当前观察者的激活状态
同时负责通知LiveData
的onActive()
和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
返回的LiveData
,LiveData
对于switchMap
来说只是个数据源控制器。
..
3-distinctUntilChanged
屏蔽LiveData
的重复数据发射。
即:LiveData
的setValue
被调用后,将会检测数据是否变更 ( 通过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()
作为入口分析:
-
mObservers
:
LiveData
的观察者列表,可以看到实际对象是ObserverWrapper
类型,即所有传入的observer
都会被ObserverWrapper
及其子类封装。 -
assertMainThread()
:
该处将会检测是否在主线程调用,否则抛出异常。 -
LifecycleBoundObserver
:
ObserverWrapper
子类,观察者的生命周期管理在此处实现。 -
existing.isAttachedTo(owner)
:
观察者不允许绑定多个生命周期,否则抛出异常。
同一个LiveData
中,观察者不能同时 持有 / 忽略 生命周期特性,两者互斥。 -
addObserver(wrapper)
:
将LifecycleBoundObserver
加入对应生命周期回调以实现自动生命周期管理
private SafeIterableMap, ObserverWrapper> mObservers = new SafeIterableMap<>();
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> 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
进行分析:
-
mObserver
:
在构造方法中传入的观察者实体,即用户构建的观察者。 -
mActive
:
当前观察者的激活状态,非激活状态时将不会触发观察者的回调。 -
mLastVersion
:
当前观察者对应的数据版本。 -
shouldBeActive()
:
判断观察者是否需要激活,由子类实现。 -
isAttachedTo()
:
判断观察者是否绑定了生命周期,由子类实现,默认为false
。 -
detachObserver()
:
观察者从LiveData
移除时,LiveData
会调用观察者包装对象的该方法,以处理必要的释放操作。 -
activeStateChanged()
:
观察者的激活状态通过该方法作出改变。
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer super T> 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);
}
}
}
- 其中第
7
点activeStateChanged()
在状态改变时,有如下性质:
-
LiveData
没有任何已激活的观察者,且此观察者激活,会回调LiveData
的onActive()
方法。 - 此观察者取消激活后,
LiveData
没有任何已激活的观察者,会回调LiveData
的onInactive()
方法。 - 观察者激活时,会通过
dispatchingValue()
通知LiveData
尝试派发数据到观察者。
- 关键方法
dispatchingValue()
:
该方法实际上LiveData
对mObservers
列表遍历进行通知尝试的方法。
当指定观察者时,尝试对该观察者派发数据;当未指定具体的观察者时,将会遍历整个mObservers
列表,对所有观察者派发数据。
-
dispatchingValue()
的具体的流程:
当前正在执行派发时,标记当次派发失效,在while
循环处重新派发;
指定派发目标时,只对该目标进行派发;
未指定派发目标时,遍历mObservers
,对所有观察者进行派发,派发期间检查失效标记,失效时,跳出当次遍历,在while
循环处重新派发。
-
mDispatchingValue
:用于标记是否真正派发数据。 -
mDispatchInvalidated
:用于标记当前派发是否失效。 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()
:
该方法比较简单,主要是就是对观察者进行激活和版本校验。
通过校验后,记录最新版本,并推送最新数据到观察者。
-
!observer.mActive
:当观察者未激活时,不执行派发。 -
observer.shouldBeActive()
:重复检查观察者是否应该处于激活状态,检查失败则通知观察者取消激活。 -
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
:
前文提到,LifecycleBoundObserver
在LiveData.observe()
时,即绑定到观察者所指定的生命周期中,而绑定通过owner.getLifecycle().addObserver()
传入自身作为对象,即LifecycleBoundObserver
必然实现LifecycleObserver
。
-
mOwner
:在构造方法中要求传入生命周期对象。 -
shouldBeActive()
:当处于生命周期处于Start - Stop之间时,观察者激活。 -
onStateChanged()
:生命周期回调。
非Destory状态,通过activeStateChanged(shouldBeActive())
进行自我状态校验和处理。
当处于Destory时,通知LiveData
移除观察者,LiveData
会把包装类从mObservers
列表中移除,且触发其detachObserver()
方法。 -
isAttachedTo()
:直接判断生命周期对象是否相同。 -
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个方法,且都比较简单,这里不贴出源码。
setValue()
:
只能在主线程执行,非主线程调用抛出异常。
mVersion
+1,mData
设置为传入数据,并通过dispatchingValue(null)
通知所有观察者数据数据更新。
注意数据设置时,不会进行任何的对比和校验。即设置相同数据时,同样视为更新数据。·postValue()
:
在任意线程中调用,传入的数据会暂存为mPendingData
,最终会通过在主线程中调用setValue(mPendingData)
进行数据更新。
注意的是,postValue()
被多次调用时,暂存数据mPendingData
会被postValue()
传入的数据覆盖,最终数据为最后一次的数据。而postValue()
发起的主线程任务,在执行到前,只会存在一个任务。即:
多次postValue()
调用,在真正主线程执行前,共享同一次任务。而其中的暂存数据mPendingData
会被覆盖为最后一次postValue()
的传入值。
使用postValue()
应该注意该问题,极短时间内多次postValue()
设置数据,会可能导致数据更新丢失。
-
LiveData.observeForever()
:
添加忽略生命周期侦测特性的观察者。
通过该方法加入的观察者不需要传入生命周期参数,即忽略生命周期侦测。
所以使用该方法时需要注意,在合适的时候调用removeObserver()
移除观察,避免发生内存泄漏。
- 通过
observeForever()
传入的观察者,将会被包装为AlwaysActiveObserver
,该包装类的shouldBeActive()
方法估计返回true
,即任何数据更新都会通知到该观察者。 - 同一个
LiveData
中,观察者不能同时 持有 / 忽略 生命周期特性,两者互斥。 - 新加入的观察者,在方法的最后都会通过
activeStateChanged(true)
通知LiveData
更新数据到观察者。
public void observeForever(Observer super T> 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个方法,且都比较简单,这里不贴出源码。
-
removeObserver(Observer observer)
:
该方法用于移除指定的观察者,如果绑定生命周期,则会解除绑定。 -
removeObservers(LifecycleOwner owner)
:
仅针对通过LiveData.observe()
添加,绑定了生命周期的观察者,移除维护中的所有生命周期对象为传入对象的观察者。最终也是通过removeObserver()
逐一移除。