1. Livedata特性
LiveData 是一种可观察的数据存储器类。并且具有生命周期感知能力,能遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。
1.1 只有当它关联的应用组件处于生命周期活跃状态时,才会通知对应观察者。
1.2 当关联的应用组件的状态变为 DESTROYED 时,便可移除此观察者,避免内存泄露。
1.3 LiveData 仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。此行为的一种例外情况是,观察者从非活跃状态更改为活跃状态时也会收到更新。此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来,值发生了更改时,它才会收到更新。
2. 原理介绍
2.1 Livedata.observe方法
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//如当前LifecycleOwner的状态的是DESTROYED,就不绑定
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//创建一个LifecycleBoundObserver(生命周期限制的观察者)
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//将观察者添加到mObservers map
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//如果已经存在并且观察者对应的LifecycleOwner不是之前绑定的LifecycleOwner报错
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//如果存在直接返回
if (existing != null) {
return;
}
//将观察者生命周期和LifecycleOwner对应的Lifecycle绑定
//当LifecycleOwner的生命周期发生变化时,回调LifecycleBoundObserver中的 onStateChanged
owner.getLifecycle().addObserver(wrapper);
}
1,observe方法先判断LifecycleOwner是否已经处于DESTROYED的状态,如果是就不绑定;
2,然后将创建一个LifecycleBoundObserver,并且将observer和LifecycleBoundObserver添加到观察者map中;
3,最后将LifecycleBoundObserver和LifecycleOwner的生命周期绑定。
2.2 LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {Å
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// 当LifecycleOwner生命周期发生变化时,调用这个函数
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//LifecycleOwner生命周期改变时,如果LifecycleOwner生命周期处于活跃状态,更新数据
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
1,当LifecycleOwner的生命周期变化是会调用LifecycleBoundObserver的onStateChanged方法;
2,判断LifecycleOwner如果处于DESTROYED,移除观察者;
3,否则如果当前是活跃状态,就将最新值通知给所有观察者。
2.3 ObserverWrapper
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;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
//有变化,且是活跃状态,更新数据
if (mActive) {
dispatchingValue(this);
}
}
}
2.4 Livedata.dispatchingValue
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果正在刷新数据,mDispatchInvalidated置为true,表示之前的刷新无效
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//如果ObserverWrapper不为null,则只刷新传入的ObserverWrapper
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//否则刷新所有观察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
//刷新数据的时候,如果在次调用此方法,则重新刷新
if (mDispatchInvalidated) {
break;
}
}
}
//刷新数据的时候,如果在次调用此方法,则重新刷新
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
1,如果传入观察者,则只刷新当前观察者,用于LifecycleOwner生命周期改变时,因为所有的观察者都绑定了LifecycleOwner的生命周期,所以这里还是刷新所有观察者;
2,如果没有传入观察者,遍历观察者map,刷新所有观察者,用于Livedata持有数据改变时;
3,如果刷新的时候,此方法被再次调用,会放弃当前刷新,重新再开始下一轮刷新。
2.5 Livedata.considerNotify
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
/ 如果当前LifecycleOwner的生命周期是非活跃,不回调onChanged
//并在LifecycleBoundObserver 中记录状态,当生命周期变为活跃,去更新数据
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//如果观察者中的数据版本大于当前版本就return,就是数据要新于观察者的数据版本时才会通知,这个setValue是在Livedata.setValue里面去自加的
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//调用观察者的onChanged
observer.mObserver.onChanged((T) mData);
}
LiveData 使用 版本号机制 来保证观察者从非活跃状态恢复时,只在“值发生变化”时才被通知
如果LiveData没有set过,当观察者从非活跃状态变为活跃状态,会收到通知吗 不会收到通知。
在 LiveData 的源码逻辑中,是否发送更新的关键依据是 mVersion(LiveData 的当前版本号)与观察者包装器的 mLastVersion 比较。
表明只有当 LiveData 的 mVersion 大于观察者上次记录的版本时,才会触发通知
当activity从created变到resumed状态,能收到几次livedate通知
1. 从 CREATED → STARTED
-
在这一步,LifecycleOwner 已进入 active(即至少 STARTED),LiveData 会调用
considerNotify()。 -
如果
LiveData当前有值(即曾调用过setValue()),那么会执行:java 复制编辑 if (mVersion > mLastVersion) { onChanged(); mLastVersion = mVersion; }这通常意味着收到一次通知。
🔄 2. 从 STARTED → RESUMED
- 这一步 Lifecycle 从活动状态变为更活跃,但它仍被
isAtLeast(STARTED)判断为 active。 - LiveData 并不会再次调用
considerNotify(),也不会重复发送当前值。
实际上,二次“激活”没有版本更新,因而不会产生新的 onChanged() 通知。
✅ 整体结论
🌟 在典型情况下,从 CREATED 一路到 RESUMED,你的观察者会接收到****一次** 通知(如果 LiveData 有值)。
- 若 LiveData 未曾设置过值(
mVersion == START_VERSION),则整个过程不会收到任何通知。 - 如果值已设置,则首次进入 active 状态时触发一次通知,后续相同生命周期状态转换不会重复触发。
2.5 Livedata.setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
setValue也是调用了dispatchingValue方法,传的参数时null,更新所有观察者。
- 1,在Livedata.observe方法先判断LifecycleOwner是否已经处于DESTROYED的状态,如果是return,不绑定,
- 2,然后将创建一个LifecycleBoundObserver,并且将observer和LifecycleBoundObserver添加到观察者map中;
- 3,最后将LifecycleBoundObserver和LifecycleOwner的生命周期绑定。
- 4,当LifecycleOwner的onStateChanged方法中,判断LifecycleOwner如果处于DESTROYED,则从map移除观察者
- 5,否则判断当前活跃状态和上次活跃状态是否相同(把生命周期抽象成活跃和非活跃状态),不相同,就调用dispatchingValue方法进行通知,在dispatchingValue方法中会比较livedata当前的mversion和observerwraper的lastversion,大于时,说明值有变化,才进行通知
- 6,setValue也是调用了dispatchingValue方法,传的参数时null,会遍历观察者map,更新所有观察者。
LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
LifecycleBoundObserver实现了LifecycleEventObserver,感知lifycleower的生命周期,继承了ObserverWrapper,可以记录observer的数据版本
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
postValue在子线程更新数据,是通过主线程的hander post一个runnable执行的的,多次设置的值,一般情况下只有最后一次会被通知给观察者,因为post的值先设置给一个mPendingData,只有mPendingData没有值时,才post一个runnable,如果有值了,就值改变mPendingData的值,不重新post值,特殊情况是主线程已经消费了这个runnale,mPendingData会重置,下次还是会在发送一个runnable,之所以只发送一次runnable是因为这个runnable是一个异步消息,会阻塞同步消息,所以不能频繁发,参考juejin.cn/post/737348…