Android Jetpack架构组件——LiveData原理篇
Posted 我就是马云飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Jetpack架构组件——LiveData原理篇相关的知识,希望对你有一定的参考价值。
前言
前面我们讲到了LiveData是如何使用的,并在最后留了几个问题。比如它是如何通过生命周期去变化的?为什么DESTORY不会接受数据?postValue和setValue是如何更新数据的?Transformations的map和switchMap方法内部是如何操作的?别急,本篇文章会带你了解其原理。接下来上正文。
LiveData是如何观察生命周期变化的?
如何观察生命周期,我们需要通过他的observe方法去看,我们上源码:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
assertMainThread("observe");
//1
if (owner.getLifecycle().getCurrentState() == DESTROYED)
// ignore
return;
//2
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//3
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//4
if (existing != null && !existing.isAttachedTo(owner))
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
if (existing != null)
return;
//5
owner.getLifecycle().addObserver(wrapper);
我在源码加了几个注释,我们一个个看。
注释一:可以看出通过当前组件的LifecycleOwner拿到生命周期的状态,如果是DESTORY就返回,不做任何处理。
注释二:新建了一个LifecycleBoundObserver包装类,并把owner和observer丢进去。
注释三:将observer和wrapper做一个存储。我们看下putIfAbsent方法:
public V putIfAbsent(@NonNull K key, @NonNull V v)
Entry<K, V> entry = get(key);
if (entry != null)
return entry.mValue;
put(key, v);
return null;
可以看出,如何这个entry存在的话,不像正常map做替换,而且直接拿到对应的value。不存在的话正常put操作。
注释四:判断这个owner是否存在,如何存在就抛出异常,提示无法添加具有不同生命周期的同一观察者。
注释五:将LifecycleBoundObserver添加到Lifecycle中完成注册,所以我们LiveData的生命周期观察其实来源于LifecycleOwner,这也就是为什么LiveData具备了观察组件生命周期变化的能力。
observe是如何同步数据的?
上面代码中我们知道有一个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);
@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实现了shouldBeActive。从命名上可以看出判读是否活跃。从代码看来也就是STARTED和RESUMED。
在看另一个,通过LifecycleEventObserver实现了onStateChanged方法。我们可以看到如果当前的STATE是DESTROYED时会移除观察者监听。接着通过判读状态是否匹配调用了activeStateChanged方法。因为prevState定义为null。所以此方法最少执行一次。那么我们看看它是如何处理的。
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);
可以看到它会先调用changeActiveCounter,字面意思也就是改变活跃的数量。
@MainThread
void changeActiveCounter(int change)
int previousActiveCount = mActiveCount;
mActiveCount += change;
if (mChangingActiveState)
return;
mChangingActiveState = true;
try
while (previousActiveCount != mActiveCount)
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
if (needToCallActive)
onActive();
else if (needToCallInactive)
onInactive();
finally
mChangingActiveState = false;
从逻辑上我们可以看出previousActiveCount默认为0,mActiveCount可能为1,可能为-1,mChangingActiveState默认为flase。也就是一定会走进while循环里面去。从里面代码可以看出需要通知组件存活状态就调用onActive,需要通知组件不活跃就调用onInactive。然后我们往回看,如果组件是活跃的就会调用dispatchingValue方法。我们接着看:
void dispatchingValue(@Nullable ObserverWrapper initiator)
//1
if (mDispatchingValue)
//2
mDispatchInvalidated = true;
return;
mDispatchingValue = true;
do
//3
mDispatchInvalidated = false;
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);
//4
mDispatchingValue = false;
注释一中mDispatchingValue用于标记当前是否处于分发状态中,如果是存在分发状态,则执行注释二表示分发无效并直接return。注释三则将分发状态修改成有效状态。我们可以看到后面无论initiator是否为null都会执行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.
if (!observer.shouldBeActive())
observer.activeStateChanged(false);
return;
if (observer.mLastVersion >= mVersion)
return;
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
可以看到当前状态如果是非活跃的就直接return了。接着判读了如果当前observer对应组件的状态不是Active,就会再次调用activeStateChanged方法,并传入false,其方法内部会再次判断是否执行onActive方法和onInactive方法回调。接着就会调用Observer的onChange方法通知数据更新。
postValue和setValue的区别是什么?
我们知道虽然我们调用observe方法对数据进行观察,但是真正同步数据的代码是postValue和setValue。话不多说,上代码:
private final Runnable mPostValueRunnable = new Runnable()
@SuppressWarnings("unchecked")
@Override
public void run()
Object newValue;
synchronized (mDataLock)
newValue = mPendingData;
mPendingData = NOT_SET;
setValue((T) newValue);
;
...
protected void postValue(T value)
boolean postTask;
synchronized (mDataLock)
postTask = mPendingData == NOT_SET;
mPendingData = value;
if (!postTask)
return;
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
@MainThread
protected void setValue(T value)
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
我们看到setValue加上了@MainThread注解,也就是在主线程中执行,并且会调用dispatchingValue传入null。这个前面我们有提到过。而postValue其实是在子线程操作,最后通过postToMainThread同步至主线程,最后其实还是调用了setValue方法。
Transformations分析
前面我们在使用篇时有提到Transformations有2个方法,一个是map。一个是switchMap。我们一个个的看。
map
@MainThread
@NonNull
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction)
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>()
@Override
public void onChanged(@Nullable X x)
result.setValue(mapFunction.apply(x));
);
return result;
我们可以看到此处调用了MediatorLiveData的addSource方法:
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged)
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged)
throw new IllegalArgumentException(
"This source was already added with the different observer");
if (existing != null)
return;
if (hasActiveObservers())
e.plug();
可以看到最后一个判断,如果存在活跃的观察者,即调用Source的plug方法。
private static class Source<V> implements Observer<V>
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer)
mLiveData = liveData;
mObserver = observer;
void plug()
mLiveData.observeForever(this);
void unplug()
mLiveData.removeObserver(this);
@Override
public void onChanged(@Nullable V v)
if (mVersion != mLiveData.getVersion())
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
我们可以看到Source提供了添加观察者,移除观察者,以及监听的操作。哎,不对,是不是发现哪里有点问题?这里它调用的是observeForever,而不是addObserver。那我们接着看:
public void observeForever(@NonNull 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);
可以看出,这里最后其实还是调用了ObserverWrapper的activeStateChanged方法。
switchMap
@MainThread
@NonNull
public static <X, Y> LiveData<Y> switchMap(
@NonNull LiveData<X> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction)
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>()
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x)
LiveData<Y> newLiveData = switchMapFunction.apply(x);
if (mSource == newLiveData)
return;
if (mSource != null)
result.removeSource(mSource);
mSource = newLiveData;
if (mSource != null)
result.addSource(mSource, new Observer<Y>()
@Override
public void onChanged(@Nullable Y y)
result.setValue(y);
);
);
return result;
可以看出来,整体和map类似,只是内部包装了一层,让其返回结果是一个LiveData而已。
总结
本篇我们整体介绍了LiveData的使用原理,也就是上篇文章遗留下来的几个问题。总之,我们不仅需要知其然,还需要知其所以然。
参考
Android Jetpack架构组件(五)带你了解LiveData(原理篇)
本文首发于我的个人博客:Android Jetpack架构组件——LiveData原理篇
更多文章请关注我的公众号:码农职场
以上是关于Android Jetpack架构组件——LiveData原理篇的主要内容,如果未能解决你的问题,请参考以下文章
Android Jetpack架构组件——什么是Jetpack?
Android Jetpack架构组件——什么是Jetpack?
Android高级Jetpack架构组件+Jetpack compose强化实战