一、前言
LiveData是一个基于观察者模式、具生命感知能力的数据包装类。
从这句话中,我们可以知道它拥有2个特点:
- 1、采用观察者模式。
- 2、拥有生命感知能力。
正是这2个特点,赋予了它不平凡的能力:
1、当LiveDate数据改变时,只会通知当前处于
活跃状态
的观察者。 2、当观察者从非活跃状态
恢复到活跃状态
时,并且在此期间,LiveDate数据有更新,也会收到数据更新的通知。 3、当生命周期处于Destroy时,自动解绑所有的观察者。
注意:
LiveData不适合作为事件Event。如:保存用户数据类,对用户是否登录进行响应。 不正确的使用方式,会导致内存泄漏。如:将Activity的生命周期,传入PupupWindow,并在其中进行响应。
二、LiveData源码解析
LiveData是一个没有抽象构造方法的抽象类,它主要有两个子类:MutableLiveData和MediatorLiveData,后续我会一一讲解。 我们先看LiveData的构造函数:
java
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
这里为LiveData中设置初始值,其中mVersion是一个同步标志位,用于LiveData数据分发,确保该LiveData每次更新数据,不会重复和缺失提示所有观察者。
其次看observe方法
java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
LifcycleOwner表示生命周期拥有者,即Activity或Fragment,后续我们称之为宿主。 1、先判断observe方法的调用是否在主线程,否则会抛异常。 2、首先判断宿主生命周期是否处于Destroy状态,不是才继续执行。 3、创建一个LifecycleBoundObserver的wrapper对象,其作用是将LiveData Observer
转换成Lifecycle Observer
,用以感知生命周期的变化。 4、将wrapper对象添加到mObservers中。
java
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
......
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
......
}
这样需要注意的是,传入的key是observer对象,并判断existing.isAttachedTo(owner)
,这意味着:
1、同一个observer对象,不能多次使用
不同的生命周期
在同一个LiveData
中进行注册。如:
kotlin
class TestFragment: Fragment() {
val liveData = MutableLiveData<Int>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
liveData.observe(this){ printlin("lifecycleOwner $it") }
liveData.observe(viewLifecycleOwner){ printlin("viewLifecycleOwner $it") }
}
}
2、一个observer可以在多个LiveData中注册,但我们通常不会这样做。 3、一个LiveData可以注册多个observer,比如页面上有多个控件使用同一份数据。
5、最后对wrapper对象添加Lifecycle生命周期监听。
到这里,LiveData和Observer就与生命周期关联起来了。接下来就只需要考虑以下2种情况:
- 1、LiveData数据改变,如何通知到Observer。
- 2、生命周期改变,如何通知到Observer。
2.1、LiveData数据改变
LiveData数据改变方式无非2种,setValue()
和postValue()
,代码如下:
java
public abstract class LiveData<T> {
volatile Object mPendingData = NOT_SET;
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);
}
}
可以看到,其实postValue()
最终也是调用到setValue()
里。ps:这里postValue()逻辑还是写的挺巧妙的,值得借鉴
。 setValue()方法中代码逻辑很简单:
- 1、检查是否是主线程
- 2、mVersion同步标志位+1
- 3、数据赋值
- 4、调用dispatchingValue,开始发送通知。
ini
public abstract class LiveData<T> {
......
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;
}
......
}
dispatchingValue()方法需要传入一个ObserverWrapper对象,当其不为null时,表示此次更新只通知该Observer;否则,表示通知所有Observer。这里我们传入的是null,即将mObservers中所有的ObserverWrapper对象依次传入considerNotify
方法中。 dispatchingValue()方法内部也做了异步处理流程,当我们调用到dispatchingValue()时,如果上一次dispatchingValue()还没执行完毕,即mDispatchingValue为true,就会将mDispatchInvalidated设置为true,表示正在更新的数据无效,并直接返回。而上一次还在dispatchingValue()中执行的代码,会被中断,并重写执行considerNotify
更新操作。 虽然目前dispatchingValue()方法都是主线程中进行调用,不存在异步执行的可能,但是该方法不是private的,即有可能够被子类调用,所以还不知Google的如此设计的用意。
java
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);
}
considerNotify()方法中代码流程:
- 1、先判断observer是否处于活跃状态,如果不是则直接退出。
- 2、此时observer一定处于活跃状态,但宿主有可能处于非活跃状态(可能宿主的状态更新事件还没来)。 如果是这样,
observer.shouldBeActive()
将返回false,就会调用observer.activeStateChanged(false)
,将observer的状态变为非活跃状态。并结束执行流程。 - 3、最后判断
observer.mLastVersion >= mVersion
,用于避免多次调用通知操作,如果同步标志为验证通过,更新标志位,最终调用到observer.mObserver的onChanged()
方法,即我们最开始给LiveData添加的Observer对象的onChanged()
回调中。
2.2、生命周期改变
当生命周期发生改变时,Lifecycle会回调到LifecycleBoundObserver的onStateChanged方法中。
java
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
......
@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();
}
}
......
}
如果Observer所对应的宿主的生命周期是否已处于DESTROYED状态,则让该Observer取消对LiveData事件订阅,并直接返回。否则调用activeStateChanged(),改变Observer的激活状态。
java
private abstract class ObserverWrapper {
......
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);
}
}
}
当Observer对象活跃时,调用changeActiveCounter(1),让活跃的对象+1,并调用dispatchingValue(this)方法,通知自身数据更新。这里我们可以看到:当宿主生命周期从非活跃状态变成活跃状态时,Observer对象会收到LiveData最新的数据更新通知。
当Observer对象不活跃时,调用changeActiveCounter(-1),让活跃的对象-1。
java
public abstract class LiveData<T> {
@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;
}
}
changeActiveCounter方法主要为了改变mActiveCount数量,并发出LiveData的活跃状态回调:
- 1、当LiveData的活跃Observer个数由0变成大于0时,调用onActive()。
- 2、当LiveData的活跃Observer个数由大于0变成0时,调用onInactive()。
注意:不是第一次活跃Observer个数由0变成大于0时,才调用onActive(),而是每次都会。onInactive()也是一样
。
2.3、observeForever
开头也说了,LiveData是一个基于观察者模式、具生命感知能力的数据包装类
。那如果我们只是个普通的类,并没有Lifecycle对象,数据的释放都需要手动执行,那LiveData就没法用了啊!
别担心,Google早就考虑到了,他们给LiveData添加了有个observeForever方法,该方法完全脱离生命周期的管理,也就意味着这个方法注册的Observer对象需要手动注销。
java
public abstract class LiveData<T> {
.......
@MainThread
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);
}
@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
assertMainThread("removeObserver");
ObserverWrapper removed = mObservers.remove(observer);
if (removed == null) {
return;
}
removed.detachObserver();
removed.activeStateChanged(false);
}
.....
}
这个流程跟observe(LifecycleOwner owner, Observer<? super T> observer)
方法很像,只不过它不需要LifecycleOwner对象。并且方法内,并没有用LifecycleBoundObserver
类,而是用的AlwaysActiveObserver
类,这两个类都继承至ObserverWrapper
。
scala
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@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 shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
......
}
这个类很简单,相比于LifecycleBoundObserver
,它没有实现LifecycleEventObserver
接口,即感知不到生命周期回调,也就不能自动解绑。 同时shouldBeActive()
方法总是返回true,表示在任何情况下,该Observer都处于活跃状态。也就是说,只要LiveData数据有更新,那通过observeForever()
添加的Observer都会收到通知。
三、MutableLiveData源码解析
MutableLiveData源码很简单,只是暴露父类LiveData的postValue
和setValue
方法。
java
public class MutableLiveData<T> extends LiveData<T> {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
四、MediatorLiveData源码解析
MediatorLiveData可以通过addSource,监听多个LiveData数据源的变化,并对这些数据源发生变化时进行响应,转化成MediatorLiveData的变化。
java
public class MediatorLiveData<T> extends MutableLiveData<T> {
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
@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();
}
}
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override
protected void onInactive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
}
MediatorLiveData也比较简单
- 1、addSource方法中,将
数据源LiveData
和Observer
包装成Source
对象,并存入mSources
中,如果MediatorLiveData的有处于激活的Observer,则调用Source的plug()方法,Source
对象将永久订阅数据源LiveData
。 - 2、removeSource方法中,从
mSources
中移除Source
对象,并调用Source的unplug()方法,让Source
对象注销对数据源LiveData
的永久订阅。 - 3、当LiveData执行onActive()时,会调用所有Source的plug()方法。
- 4、当LiveData执行onInactive()时,会调用所有Source的unplug()方法。
这意味着:当MediatorLiveData处于活跃状态时,如果数据源LiveData
数据改变,都会回调到Source对象中。反之,而如果处于非活跃状态时,就不会回调到Source对象中。
java
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);
}
}
}
其实从代码层面看,源LiveData
并没有observe
到MediatorLiveData
中,MediatorLiveData
只是为源LiveData
提供一个统一的生命周期环境。 使用MediatorLiveData需要注意的地方:
如果一个MediatorLiveData添加了A、B两个源LiveData,且对应的Observer都会给MediatorLiveData赋值。 当inActive时,A、B两个源LiveData都发生数据改变,则Active后,MediatorLiveData只会响应
最后一次添加
的源LiveData的数据变化。
java
public class MainActivity extends AppCompatActivity {
private MediatorLiveData<Integer> liveData = new MediatorLiveData<>();
private LiveData<Integer> sourceA = new MutableLiveData<>();
private LiveData<Integer> sourceB = new MutableLiveData<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
liveData.addSource(sourceA, integer -> liveData.setValue(integer));
liveData.addSource(sourceB, integer -> liveData.setValue(integer));
liveData.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
Toast.makeText(MainActivity.this, "result: " + integer, Toast.LENGTH_SHORT).show();
}
});
}
}
五、高级用法
5.1、Transformations.map
LiveData的数据,不会通知inActive的观察者,但是当观察者恢复到active后,会得到最新的data数据更新。
kotlin
@MainThread
@NonNull
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source, @NonNull final Function<X, Y> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(func.apply(x));
}
});
return result;
}
5.2、Transformations.switchMap
用于多数据源的切换和控制
java
@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;
}
5.3、Transformations.distinctUntilChanged
普通LiveData,只要调用setValue,都会回调到Observer(激活状态下)。 而提供distinctUntilChanged方法,只有数据在变化时,才会回调到Observer中。
java
@MainThread
@NonNull
public static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {
final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();
outputLiveData.addSource(source, new Observer<X>() {
boolean mFirstTime = true;
@Override
public void onChanged(X currentValue) {
final X previousValue = outputLiveData.getValue();
if (mFirstTime
|| (previousValue == null && currentValue != null)
|| (previousValue != null && !previousValue.equals(currentValue))) {
mFirstTime = false;
outputLiveData.setValue(currentValue);
}
}
});
return outputLiveData;
}