前言
Google Android开发者 LiveData概览
在了解LiveData
源码之前,建议先了解LifeCycle
相关知识,请参考:Android JetPack深入分析Lifecycle源码
定义
LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
从定义中,我们可以大概知道:LiveData
是一个数据存储类,能够感知Activity
、Fragment
等组件的生命周期,并且支持对它存储的数据进行观察;
使用LiveData的好处以及如何使用这里就不再过多赘述,更多查看Google官方文档;
这里就直接进入正题,源码分析LiveData是如何实现生命周期监听以及数据更新的;
绑定观察者
调用LiveData.observe()
方法会进行对应观察者绑定,相关代码如下:
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
//LifecycleOwner对应被观察者,Observer对应观察者
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//1.进行主线程判断,不是主线程中调用直接抛异常;
assertMainThread("observe");
//2.如果被观察者已销毁,则直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//3.将观察者和被观察者包装成LifecycleBoundObserver对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//4.mObservers是以Observer为key,LifecycleBoundObserver为value的,内部采用双链表结构存储,根据传入的观察者Observer查询LifecycleBoundObserver,如果没查到,则将observer, wrapper以Entry<K,V>形式插入到链表中,如果已存在,则直接返回对应的ObserverWrapper
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//5.如果链表中已存在&&绑定的是同一个被观察者,则抛异常;
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//6.如果已存在,则直接返回
if (existing != null) {
return;
}
//7.由前面的Lifecycle源码分析可知,最终将wrapper添加到LifecycleRegistry中维护的观察者集合中;
owner.getLifecycle().addObserver(wrapper);
}
其中LifecycleBoundObserver
类相关代码如下:
//1.实现了LifecycleEventObserver接口,而我们知道LifecycleEventObserver继承于LifecycleObserver,因此上述可以将LifecycleBoundObserver存储到LifecycleRegistry中维护的观察者集合中;
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//当前被观察者是否处于活跃状态,即state应该>=STARTED,对应STARTED和RESUMED两种状态
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//Lifecycle源码分析中,分发生命周期事件的时候,会执行此onStateChanged方法
@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);
}
}
//内部维护了 观察者、观察者活跃标志、观察者对应版本号信息
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;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
}
小结
从上面源码分析,我们可以知道,LiveData绑定观察者
会将观察者
以及被观察者
包装LifecycleBoundObserver
对象【内部持有观察者
、被观察者
、观察者版本号
、观察者活跃标志
等信息】,并在其内部维护了一个双向链表结构用于存储LifecycleBoundObserver对象,最终会将观察者添加到LifecycleRegistry
维护的观察者集合中,从而实现生命周期的监听!!!
更新数据
LiveData.postValue
最终调用的也是LiveData.setValue()
方法,只是做了下切换到主线程,这里就直接看LiveData.setValue()
方法;
public abstract class LiveData<T> {
//当前LiveData对应的版本号
private int mVersion;
//当前是否正在刷新数据
private boolean mDispatchingValue;
//刷新标记
private boolean mDispatchInvalidated;
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
}
setValue
方法主要做了以下几件事:
- 判断执行线程是否是主线程;
- 当前版本号+1;
- 将传入的
value
设置给全局变量mData
; - 执行
dispatchingValue(null)
进行数据分发;
我们紧接着看下dispatchingValue(null)
方法:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//1.如果正在刷新数据,标记之前的刷新数据无效,mDispatchInvalidated = true会影响正在for循环中的逻辑
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
//2.设置正在刷新
mDispatchingValue = true;
do {
//3.修改刷新非法标记为false
mDispatchInvalidated = false;
if (initiator != null) {
//4.如果传入initiator,表示只通知对应的观察者更新数据
considerNotify(initiator);
initiator = null;
} else {
//5.遍历所有观察者,调用considerNotify方法进行数据更新;
//这里是do-while逻辑,会先执行一遍do操作,遍历所有的观察者进行数据更新,如果在更新过程中再次调用了setValue方法
//则会先跳出循环,重新遍历所有观察者通知数据更新【mDispatchInvalidated为true】
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
dispatchingValue()
方法中会判断mDispatchingValue【当前是否正在分发数据】
,如果不是则遍历所有观察者进行分发,如果当前正在分发数据【setValue方法没执行完被再次调用】,则会先跳出观察者遍历,重新进行一次观察者遍历数据分发;【假设initiator传入为null】,具体数据更新由considerNotify
方法完成;
private void considerNotify(ObserverWrapper observer) {
// 1.active状态检查
if (!observer.mActive) {
return;
}
//2.判断当前观察者是否处于活跃状态【被观察者生命周期状态为STARTED,RESUMED】
if (!observer.shouldBeActive()) {
//3.设置mActive为false,不回调onChanged方法;
observer.activeStateChanged(false);
return;
}
//3.版本比对,mLastVersion默认为-1,而mVersion默认为0,因此会导致粘性事件产生【后注册的观察者会接收到前面的数据更新操作】,如果不想粘性,这里可以通过hook修改mLastVersion和mVersion一致实现;
if (observer.mLastVersion >= mVersion) {
return;
}
//4.同步观察者版本号和LiveData版本号一致;
observer.mLastVersion = mVersion;
//5.回调观察者对应的onChanged方法
observer.mObserver.onChanged((T) mData);
}
considerNotify()
方法中会进行生命周期活跃
和版本号
判断,满足条件,最终会回调Observer.onChanged()
方法!!!
更新数据流程图
文章来源:https://www.toymoban.com/news/detail-529006.html
结语
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )文章来源地址https://www.toymoban.com/news/detail-529006.html
到了这里,关于Android JetPack深入分析LiveData源码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!