LiveData是实现MVVM的关键组件。LiveData基于观察者模式,是一个观察者主体的数据持有类。
不同于普通的观察者主体,LiveData是对生命周期敏感的,即它能感知activity、fragment或service等组件的生命周期。因此可以在适当的时刻结合ViewModel和底层数据存储修改前台与数据相关的UI。
LiveData封装在ViewModel中使用。ViewModel的生命周期与创建它的组件UI一致,且ViewModel能在因配置改变而导致的activity销毁、重建的过程中存活,避免了数据的重复创建,提高了性能,是实现数据和UI解耦的关键组件。
通过observe()方法绑定UI组件和观察者;
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
assertMainThread("observe");//必须在主线程中调用
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
......
......//省略代码,检测是否重复插入和冲突处理
owner.getLifecycle().addObserver(wrapper);//wrapper将观察UI组件的生命周期
}
这里能够很清晰的看到观察者模式——向mObservers中添加一个wrapper(封装了UI组件和观察者);
wrapper本身也是个观察者,它将观察UI组件的生命周期变化(最后一行代码);
这个简单的方法实现了LiveData和UI组件的相互观察。
LifecycleBoundObserver也实现了Observable接口:
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//当UI组件被销毁时,LiveData会自己销毁注册的观察者,所以不必担心内存泄露问题
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
LiveData会自己解除已不再栈中的UI组件,所以我们不必担心内存泄露问题。
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {//状态不变,直接返回
return;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {//传递、更新数据
dispatchingValue(this);
}
}
当状态没变时,直接返回;
如果当前状态为active,且观察者数目从0变为1,则会调用onActive回调;
若当前状态不是active且观察者数目仍为0,则调用onInactive回调。MutableLiveData中开发者可自己实现上述回调。
最后dispatchingValue()传递并更新数据。上述即为LiveData对UI组件生命周期监测的处理流程。
(图片来源:https://medium.com/@elye.project/understanding-live-data-made-simple-a820fcd7b4d0)
从LiveData.setValue()着手:
//该方法需在主线程中调用
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
dispatchingValue():
void dispatchingValue(@Nullable ObserverWrapper initiator) {
......
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
//监听UI状态变化时的更新逻辑
considerNotify(initiator);
initiator = null;
} else {
//LiveData主动调用setValue()更新逻辑
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
调用considerNotify();
private void considerNotify(ObserverWrapper observer) {
//再次映射组件非active,不会更新数据
if (!observer.mActive) {
return;
}
//active的管理
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//状态版本管理
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//调用观察者的更新方法
observer.mObserver.onChanged((T) mData);
}
逻辑一目了然,不再多说。
最简单的LiveData,封装在ViewModel内部:
public class MyViewModel extends ViewModel {
private MutableLiveData mNormalData = new MutableLiveData<>();
......
//注册观察者
public void observeNormal(LifecycleOwner owner, Observer observer) {
mNormalData.observe(owner, observer);
}
......
//更新数据
public void increment() {
Integer value = mNormalData.getValue();
if (value == null || value == 0) {
mNormalData.setValue(1);
} else {
mNormalData.setValue(++value);
}
}
......
}//class ends
Observer:
//匿名内部类会持有外部类的引用,可能造成内存泄露,但对LiveData无碍;
//通过回调更新UI
private Observer getObserver() {
if (mObserver == null) {
mObserver = new Observer() {
@Override
public void onChanged(Object o) {
if (o instanceof Integer) {
mViewText.setText(String.valueOf(o));
}
}
};
}
return mObserver;
}
MediatorLiveData扮演了一个数据容器的角色,多个数据源可绑定至MediatorLiveData,从而多个数据源的改变可应用到UI。
数据成员封装在ViewModel中:
public class CounterViewModel extends ViewModel {
private MediatorLiveData mMediator = new MediatorLiveData<>();
private MutableLiveData mMergeA = new MutableLiveData<>();
private MutableLiveData mMergeB = new MutableLiveData<>();
private MergerObserver mObserverA = new MergerObserver() {
@Override
public void onChanged(Object o) {
super.onChanged(o);
if (o instanceof Integer) {
StringBuilder sb = new StringBuilder();
sb.append("A: ").append( o);
mMediator.setValue(sb.toString());
}
}
};
private MergerObserver mObserverB = new MergerObserver() {
@Override
public void onChanged(Object o) {
super.onChanged(o);
if (o instanceof Integer) {
StringBuilder sb = new StringBuilder();
sb.append("B: ").append( o);
mMediator.setValue(sb.toString());
}
}
};
}
通过addSourcej将子数据源绑定到MediatorLiveData:
private void initMediator() {
mMediator.addSource(mMergeA, mObserverA);
mMediator.addSource(mMergeB, mObserverB);
}
MediatorLiveData和外部UI组件绑定;
public void observeMediator(LifecycleOwner owner, Observer observer) {
mMediator.observe(owner, observer);
}
当mMergeA或mMergeB的数据变化时,会调起其观察者(mObserverA、mObserverB)的回调;
观察者的回调实现很重要,对数据进行处理后,必须更新MediatorLiveData的数据,从而才会引起在UI端的回调。
MediatorLiveData是一种双重观察的模式:ObserverA和ObserverB分别观察源数据A和B;UI组件端观察MediatorLiveData。在ObserverA和ObserverB得到更新数据时,必须在回调中处理数据且更新MediatorLiveData(即调用MediatorLiveData.setValue()),从而调起UI端回调。
(图片来源:https://medium.com/@elye.project/understanding-live-data-made-simple-a820fcd7b4d0)
从添加数据源addSource()看起:
@MainThread
public void addSource(@NonNull LiveData source, @NonNull Observer super S> onChanged) {
//创建Source对象,并添加到mSource中;
Source e = new Source<>(source, onChanged);
Source> existing = mSources.putIfAbsent(source, e);
......
......//检查重复和冲突
//MediatorLiveData未绑定观察者时,不会调用
if (hasActiveObservers()) {
e.plug();
}
}
Source封装了数据源和观察者,且Source自己实现了观察者接口。该步骤主要逻辑就是往mSource里添加Source对象。
MediatorLiveData使用的是LiveData的observe()(如前所述),但是其在初次添加了观察者的回调里有自己的实现逻辑:
protected void onActive() {
for (Map.Entry, Source>> source : mSources) {
source.getValue().plug();
}
}
遍历了每个Source,并调用其plug()方法,其中直接调用了LiveData.observeForever()
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
......
......//检查重复和冲突
wrapper.activeStateChanged(true);
}
与observe()不同的是,其中wrapper类型不一样,为AlwaysActiveObserver:
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
所以该Observer永远都是active的。
所以,plug()方法就是将各个数据源和它对应的观察者建立了观察的关系。