本文基于:
androidx.lifecycle:lifecycle-viewmodel:2.3.0
androidx.lifecycle:lifecycle-livedata-core:2.3.0
一.LiveData简介
LiveData是google随Jetpack发布的,是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。详细的文档介绍参考:
https://developer.android.com/topic/libraries/architecture/livedata
二.LiveData原理
1. 示例
这个例子基于之前ViewModel的例子(https://blog.csdn.net/Beatles_The/article/details/114793959),在ViewModel里,我们通过interface OnTimeChangeListene来处理数据的变化监听,是一种观察者模式,Activity中使用的时候需要先调用setOnTimeChangeListener把观察者传入,在ViewModel中保存一个观察者列表,在被观察的数据变化时,调用观察者的onTimeChanged方法。如果要观察的数据很多,则需要定义大量的接口,代码显得冗余。LiveData组件就是为了简化这个而来的,帮助我们完成ViewModel与页面组件之间的通信。所以,LiveData通常是被放在ViewModel中使用。
public class MyLiveDataViewModel extends ViewModel {
private static final String TAG = "MyLiveDataViewModel";
private Timer mTimer;
private MutableLiveData<Integer> mCurrentSecond;
public void startTiming() {
if (mTimer == null) {
mCurrentSecond.setValue(0);
mTimer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
mCurrentSecond.postValue(mCurrentSecond.getValue() + 1);
}
};
mTimer.schedule(timerTask, 1000, 1000);
}
}
public LiveData<Integer> getCurrentSecond() {
if (mCurrentSecond == null) {
mCurrentSecond = new MutableLiveData<>();
}
return mCurrentSecond;
}
@Override
protected void onCleared() {
super.onCleared();
Log.d(TAG, "onCleared()");
mTimer.cancel();
}
}
public class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewmodel);
final Button tvLiveTime = findViewById(R.id.btn_demo_livedata_viewmodel);
ViewModelProvider vmp = new ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(
this.getApplication()));
MyLiveDataViewModel liveDataViewModel = vmp.get(MyLiveDataViewModel.class);
final MutableLiveData<Integer> liveData = (MutableLiveData<Integer>)
liveDataViewModel.getCurrentSecond();
liveData.observe(this, new Observer<Integer>() {
@Override
public void onChanged(@Nullable Integer second) {
runOnUiThread(() -> tvLiveTime.setText("LIVE-TIME:" + second));
}
});
liveDataViewModel.startTiming();
}
}
运行后,和之前ViewModel的demo效果是一样的,这里去掉了回调的Listener接口,由LiveData来实现。
2. 注册Observer
我们先看一下,LiveData的类图:
LiveData的结构其实很简单,也是一个观察者模式,LiveData内部保存一个mObservers的列表,和Lifecycle类似,observer()方法传入的Observer对象会被包装成LifecycleBoundObserver,observerForever()方法传入的Observer对象会被包装成AlwaysActiveObserver。二者的区别是LifecycleBoundObserver实现了LifecycleObserver,当LifecycleOwner生命周期结束时,会被自动的从mObservers中remove掉:
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
......
}
所以observer()的第一个参数需要传入LifecycleOwner对象。
3. 数据变化分发
当数据变化时,调用LiveData的setValue和postValue进行更新,在主线程的时候调用setValue,否则调用postValue,其内部最终也是调用setValue,setValue的流程如下:
其中,dispatchValue可以指定Observer,这时候只通知这个Observer,如果没有指定,则循环所有的Observer。dispatchValue考虑了多线程同时调用的情况:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
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);
mDispatchingValue = false;
}
第一个线程setValue后,会设置mDispatchingValue,然后尝试通知列表每一个观察者,比如通知到一半,这个时候,第二个线程setValue后,请求dispatchValue的时候,通过mDispatchingValue的值发现正在更新,它会mDispatchInvalidated设置并直接退出,第一个线程通知过程发现mDispatchInvalidated被设置,直接break,从当前的列表中循环中退出,在外层循环中发现mDispatchInvalidated被设置,从头开始通知列表。如下示意图:
列表中5个Observer,Thread1调用setValue(2),将LiveData的值设置为2,接下来通知列表,通知到第三个的时候,Thread2调用setValue(3),将LiveData的值设置为3,这个时候Thread2将退出,然后Thread1重头开始通知列表。
这里的解释都是基于多线程,按理说mDispatchingValue和mDispatchInvalidated需要设置volatile,但是源码中并没有,mData是volatile的:
private volatile Object mData;
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
个人觉得mDispatchingValue和mDispatchInvalidated需要设置volatile,但是不设置,可能问题也不大,因为mData是volatile的,上面的例子中,如果第二个线程setValue(3),在dispatchingValue的时候,判断mDispatchingValue是false(因为没有同步导致的),那么Thread2也会执行一遍通知,但是通知的数据是对的,同样Thread1由于mDispatchInvalidated判断不对的原因,不会提前结束旧的通知,但是其mData已经是新的。也就是说,不设置volatile,可能导致通知变多,但数据并没有通知错。而且即使设置了,有的Observer也会通知多次,例如上面的例子,前3个Observer会通知2次。
4. 数据Active
前面的类图可以看到LiveData有两个自身生命周期有关的方法onActive和onInactive,LiveData的Active的定义是至少有一个Observer是Active的。ObserverWrapper里有一个activeStateChanged方法,这个是处理Observer的Active状态的,先来看其实现:
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);
}
}
mActive是ObserverWrapper当前的活跃状态,接下来调用的changeActiveCounter是LiveData的方法,不是ObserverWrapper的,实现如下:
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;
}
}
只是一个简单的计数,如果发现旧的ActiveCount是0,新的大于0,说明有Observer是活跃的,那么LiveData也是活跃的,调用onActive,反过来,旧的ActiveCount大于0,新的是0,说明没有Observer是活跃的,那么LiveData也是不活跃的,调用onInactive。
activeStateChanged最后一个处理逻辑,如果该Observer是被激活的,则调用dispatchingValue(this)去通知状态,前面知道dispatchingValue参数是一个Observer的话,会调用该Observer的onStateChange的回调。
接下来看看什么情况下会调用上面的activeStateChanged:
(1)observeForever,由于这个Observer不依赖生命周期,一旦被注册,直接调用activeStateChanged(true),表示激活。
(2)removeObserver,移除Observer,调用activeStateChanged(false),表示非激活状态。
(3)onStateChanged,这个是LifeCycle的生命周期回调,也就是说ObserverWrapper生命周期变化时,会调用activeStateChanged(shouldBeActive()),shouldBeActive判断生命周期是不是Active的:
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
(4)considerNotify,前面已经分析,这个是通知状态变化时的方法,其内部调用Observer的onStateChange,在调用前,会判断这个Observer是否还是存活的,这个是为了预防在处理通知的过程中,某些Observer已经不是存活的(比如执行removeObserver但是还没有收到事件):
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
三.总结
结合LiveData和ViewModel,可以很方便的监听数据的变化,其本质也是一个观察者模式,不需要定义各种interface来回调数据变化的方法,都放到onStateChange中来回调。