1. LiveData简介
1.LiveData 是一种可观察的数据存储器类。
与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
2.观察者生命周期在STARTED 或 RESUMED状态, LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。
3.当activity 或 fragment销毁时,系统会自动移除数据观察者
2. Livedata 简单使用
vm.livedata.observe(this){
}
livedata.value = ""
3. 源码分析
1. liveDta 如何感知生命周期的变化,
livedata.observe(this)
abstract class LiveData<T> {
//观察者容器
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
//owner 生命周期拥有者
//observer 数据观察类
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//当生命周期状态==DESTROYED时,不会添加
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
//
return;
}
// 将owner和observer组合,使得LifecycleBoundObserver拥有生命周期和数据观察2种功能
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;
}
//注册生命周期,这样LifecycleBoundObserver就能感知owner生命周期的变化
//重新添加的的观察者会重走各个生命周期直到相等
//这也是时livedata粘性的关键之一
owner.getLifecycle().addObserver(wrapper);
}
}
LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
//生命周期拥有着
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
//包装成 ObserverWrapper
super(observer);
mOwner = owner;
}
//当前生命周期状态至少大于STARTED
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//生命周期发生改变
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
//从观察者列表种移除
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
//状态变化通知,
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
//是否关联了生命周期持有者
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
//移除生命周期观察者监听
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
ObserverWrapper
private abstract class ObserverWrapper {
//真正观察者
final Observer<? super T> mObserver;
//是否活跃
boolean mActive;
//当前数据观察者的版本号 -1
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;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
//活跃状态下分发数据
//它时粘性的,当新添加的观察者处于活跃时,分发
dispatchingValue(this);
}
}
}
2.livedata 如何储存和分发数据的
LiveData
abstract class LiveData<T> {
final Object mDataLock = new Object();
//初始版本号
static final int START_VERSION = -1;
static final Object NOT_SET = new Object();
int mActiveCount = 0;
//当前存储数据
private volatile Object mData;
//初始值
volatile Object mPendingData = NOT_SET;
//当前版本号
private int mVersion;
}
setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
//版本号++
mVersion++;
//赋值给成员mData,
mData = value;
//分发给当前的活跃的观察者
dispatchingValue(null);
}
postValue 会丢失值
当频繁使用postValue()更新时,post(1)但第一次的mPostValueRunnable消息还没执行,
第二次post(2) 的值已经更新了mPendingData = 2,
导致第一次的Runnable拿到的是第二次的 2,第一次post(1)会被覆盖,
导致数据丢失。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
//将值暂时存到mPendingData中
mPendingData = value;
}
if (!postTask) {
return;
}
//向主线程发生消息
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
//获取postValue存储的值
newValue = mPendingData;
mPendingData = NOT_SET;
}
//分发
setValue((T) newValue);
}
};
dispatchingValue
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//当某观察者持有的生命周期状态发生变化时,通知更新
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//value值发生改变时
//遍历所有的观察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
considerNotify
private void considerNotify(ObserverWrapper observer) {
//当前观察者是否活跃
if (!observer.mActive) {
return;
}
// 检查当前生命周期组件状态是否活跃
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//当前观察者的版本号 >= LiveData版本号,
//说明已经分发过,值已经时最新的了
if (observer.mLastVersion >= mVersion) {
return;
}
//更新观察者版本号
observer.mLastVersion = mVersion;
//通知观察者,数据更新
observer.mObserver.onChanged((T) mData);
}
4. 总结
LiveData是能感知生命周期,粘性,可观察的数据存储器类。
通过Lifecycle感知生命周期的变化,确保LiveData只更新处于活跃活跃生命周期状态的应用组件观察者,
通过储存value值和lifecycle来通知观察者更新旧值。
为了使用方便,官方还提供了多个转换操作:
androidx.lifecycle.Transformations
//map livedata值的变换
val liveData1 = _livedata.map {
it.length
}
//switchMap 一个livedata的变化,触发另一个livedata的更新
//一对一
val liveData2 = _livedata.switchMap {
val liveData = MutableLiveData<String>()
liveData.value = it
liveData
}
//去重操作符
_livedata.distinctUntilChanged()
//mediatorLiveData 可监听多个livedata数据源的变化
//一对多
val mediatorLiveData = MediatorLiveData<Any>()
mediatorLiveData.addSource(liveData1){
mediatorLiveData.value = it
}
mediatorLiveData.addSource(liveData2){
mediatorLiveData.value = it
}
//上述操作都发生在主线程,当处理复杂业务liveData{}
//CoroutineLiveData
//默认在主线程的协程中运行,
//可指定上下文分发器,如Io线程
val livedata = _livedata.switchMap {
liveData(Dispatchers.IO){
emit("xxx")
}
}