一、LiveData概述
根据官方文档描述,LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

LiveData一般由ViewModel或一些组件持有,当持有者对LiveData进行数据更改时,如果观察者(Observer)处于STARTED或RESUMED状态,则LiveData认为观察者处于ACTIVE状态,正常更新通知。如果观察者处于Paused、Stopped、Destroyed状态,即处于非ACTIVE状态,这些观察者则不会收到通知。
幸运的是,注册与实现LifecycleOwner接口的对象配对的观察者时,当相应的lificycle对象状态变为 DESTROYED时,便可移除此观察者,尤其对Activity和Fragment有用,因为可以放心订阅LiveData对象而不用担心内存泄露,因为当Activity和Fragment生命周期被销毁时,系统会立即退订它们。
二、LiveData子类
LiveData是一个抽象类,无法直接使用,但Android提供一些子类,方便我们使用。
MutableLiveData
MutableLiveData是LiveData的最简单的实现,可以接收数据并通知观察者。
使用方式如下:
// 创建MutableLiveData对象
val liveData = MutableLiveData<String>()
// 获取liveData中的原始数据,会触发getValue方法
val stringData = liveData.value
// 修改数据,会触发setValue方法
liveData.value = someValue
// postValue会向主线程传递一个Runnable,并发地更改数据
liveData.postValue(someValue)
监听LiveData的方式
// 创建观察者
val dataObserver = Observer<String> { newData ->
// 进行一些更新操作
textView.text = newData
}
在这里举个例子,在Activity里面创建LiveData,Fragment进行观察
class MainActivity : AppCompatActivity() {
val liveData = MutableLiveData<String>()
private val changeObserver= Observer<String> { value ->
// 当value不为null时,给对应的textView赋值
value?.let {
live_data_textView.text = it
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 监听liveData,并改变UI
liveData.observe(this, changeObserver)
generate_btn.setOnClickListener {
// 点击按钮更改为随机值
liveData.value = (1..9999).random().toString()
}
}
}
class MainFragment : Fragment() {
...
override fun onAttach(context: Context) {
super.onAttach(context)
getLiveData().observe(this, Observer { value ->
// 进行UI更改
value?.let {
textView.text = it
}
})
}
private fun getLiveData(): LiveData<String> {
// 获取activity中的liveData
return (active as MainActivity).liveData
}
}
当Activity中的LiveData数据发生变化,Fragment中的UI也会跟着变化。
订阅LiveData的代码是这行
getLiveData().observe(this, changeObserver)
即使在Activity或Fragment销毁时没有取消订阅,liveData也不会通知这些inactive的Acitivity或Fragment而导致Crash。
MediatorLiveData
如果现在需要同时监听两个LiveData时,如何将这两个LiveData结合起来,这就要用到MediatorLiveData,可以将多个LiveData结合起来,最终以一个LiveData的形式提供给外部监听。

使用方法如下
val liveData1: LiveData<Int> = ···
val liveData2: LiveData<Int> = ···
// 创建
val result = MediatorLiveData<Int>()
// 方法addSource用于添加一个LiveData,第一个参数是LiveData,第二个参数是Observer
// result随liveData1变化
result.addSource(liveData1) { value ->
result.setValue(value)
}
// result随liveData2变化
result.addSource(liveData2) { value ->
result.setValue(value)
}
// 取消订阅liveData1
result.removeSource(liveData1)
举个例子,用户分别输入了FirstName和LastName,界面显示的FullName要随时变化,实现如下
fun getFullName(firstName: LiveData<String>, lastName: LiveData<String>): LiveData<String> {
val result = MediatorLiveData<String>()
result.addSource(firstName) { value ->
result.value = firstName.value + lastName.value
}
result.addSource(lastName) { value ->
result.value = firstName.value + lastName.value
}
return result
}
Transformations
map
很多时候,从API拿到的数据并不是UI数据的格式,需要在中间做一些处理,可以用静态方法map
val UIResult = Transformations.map(repository.getLiveData()) { data ->
convertData(data)
}
可以看下map的源码,其实很简单
@MainThread
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;
}
map方法总共有两个参数
LiveData<X> source:需要做处理的liveDatafinal Function<X, Y> mapFunction:将liveData作处理的映射函数,参数是liveData的数据类型,返回值是生成的liveData的数据类型。
生成的LiveData---result其实是MediatorLiveData类型,result调用了addSource将source添加进去,监听函数处理仅仅是将source的数据经过mapFunction处理后生成的值赋值给result,这样result可以随source的变化而变化。
switchMap
通过上面的一些讲述,可以很容易的同时监听多个LiveData,如果需要从多个LiveData中选择一个LiveData进行监听,可以用静态方法switchMap
使用方法如下
// 根据不同的user获取对应的user数据
val transformSwitchedLiveData = Transformations.switchMap(userManager.userLiveData) { user ->
getDataForUser(user)
}
switchMap的源码同样很容易理解
@MainThread
public static <X, Y> LiveData<Y> switchMap(
@NonNull LiveData<X> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
// 监听source的数据变化
result.addSource(source, new Observer<X>() {
// 根据source不同数据生成的LiveData
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
// 由switchMapFunction生成对应的LiveData<Y>
LiveData<Y> newLiveData = switchMapFunction.apply(x);
// 如果和上次一样,不做任何更改
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
// 如果的新的LiveData,则需要取消监听上次的LiveData
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
// 监听新的liveData
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
switchMap有两个参数
LiveData<X> source:作为swtichMapFunction参数的LiveDatafinal Function<X, LiveData<Y>> switchMapFunction:监听source的数据变化,并由不同的数据返回相应的LiveData<Y>,同时也会监听生成的LiveData<Y>
总的来说,返回值result仍然是一个MediatorLiveData,监听了source的变化,重点是在监听函数中。
每当source变化时,都会由switchMapFunction生成新的newLiveData,存储在Observer中的mSource中,此时有两种情况:
- 如果
newLiveData和之前的mSource一样,则什么都不做。 - 如果不一样,将上次
mSource从result监听列表中删除,保持始终只会监听一个,然后将newLiveData赋值给mSource,并将新的mSource添加入result的监听列表中。
三、LiveData解析
LiveData
构造函数
LiveData总共有两个构造函数,一个无参,一个有参。
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
两个构造函数均对实际储存的值mData进行初始化,以及并发所用的mVersion进行初始化。
其中mData的定义如下
private volatile Object mData;
用volatile修饰了mData,使其读写能在并发中具有一致性。
NOT_SET是一个常量,表示一个未设置初始值的值,START_VERSION用于初始化mVersion,在并发中使用。
static final Object NOT_SET = new Object();
static final int START_VERSION = -1;
订阅
ObserverWrapper

在解释observe函数之前需要先理解ObserverWrapper这个内部类。
首先持有了对LiveData<T>的观察者对象
final Observer<? super T> mObserver;
其中有三个等待子类具体实现的方法,这三个方法就简单说明
// 判断Observer是否处于Active状态
abstract boolean shouldBeActive();
// 判断Observer是否注册到了一个LiftcycleOwner
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
// 取消注册
void detachObserver() {
}
下面这个函数就很重要了
void activeStateChanged(boolean newActive) {
// 如果active状态与之前一样,什么都不做
if (newActive == mActive) {
return;
}
// 将新的active状态赋值
mActive = newActive;
// 监听LiveData所有Observer如果都处于inactive,则认为整体为inactive
boolean wasInactive = LiveData.this.mActiveCount == 0;
// 对于Observer的active状态,将LiveData所持有的mActiveCount进行更改
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
// 如果Observer是active状态,则Observer进行通知
if (mActive) {
dispatchingValue(this);
}
}
activeStateChanged做的事就是当Observer从active变为inactive,或者从inactive变为active,进行通知,如果当前状态为active,则通知所有的Observer,这就是当一个Fragment或Activity状态变更时,依然能正常收到最新的值。
LifecycleBoundObserver
LifecycleBoundObserver是ObserverWrapper的子类,并实现了LifecycleEventObserver接口,实现Observer与Activity或Fragment的生命周期进行绑定。
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
构造函数与相比较ObserverWrapper多了一个参数LifecycleOwner owner,可以监听Activity或Fragment的生命周期。
重写方法如下:
@Override
boolean shouldBeActive() {
// 当owner的状态为STARTED或RESUMED时,此Observer才认为是Active
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
// 从owner的生命周期上移除该Observer
mOwner.getLifecycle().removeObserver(this);
}
实现对生命周期的监听正是重写了LifecycleEventObserver的onStateChanged方法
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
// 如果当前生命周期已经是DESTROYED,那么就从LiveData中移除该Observer
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
// 调用LiveData的removeObserver方法
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
当一个Activity或Fragment被销毁时,其中订阅的Observer会自动从LiveData的Observer列表中移除,不会发生通知了一个已经销毁的Observer而导致Crash,并且每次生命周期改变都会触发activeStateChanged,及时通知观察者。
observe

说了这么久,终于到了对应的observe方法,LiveData用一个SafeIterableMap保存了所有订阅该LiveData的Observer和与之绑定的LifecycleOwner。
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
observe方法体
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe"); // 主线程才能调用
// 如果绑定的LiftcycleOwner处于DESTROYED状态,则不会绑定成功
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 从mObservers插入对应的observer,如果是同一observer,则会返回对应的wrapper,反之则是null
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
// 如果是同一observer,且想要绑定到不同的LifecycleOwner,则会抛出异常
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
// 同一Observer不会重复绑定
if (existing != null) {
return;
}
// 将Observer绑定到生命周期
owner.getLifecycle().addObserver(wrapper);
}
observe方法生成Observer与LifecycleOwner绑定的LifecycleBoundObserver对象,LifecycleBoundObserver会监听LifecycleOwner的生命周期,并做出相应的改变。在添加到mObservers之前会做对应的检查,避免同一Observer绑定到不同的owner以及重复绑定。
通知

当LiveData的值改变时,需要通知所有观察者,而改变LiveData值有两个方法setValue和postValue,此处先讲比较简单的setValue
setValue
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
// 每次更改value都会使version+1
mVersion++;
mData = value;
// 通知所有的Observer
dispatchingValue(null);
}
setValue更改真实数据mData,并通知所有的观察者。
dispatchingValue
void dispatchingValue(@Nullable ObserverWrapper initiator) {
// 解决并发操作,当正在颁发中,如果有新的数据变更,则不会再次通知观察者
// 如果正在分发则直接返回
if (mDispatchingValue) {
// 标记分发失败
mDispatchInvalidated = true;
return;
}
// 标记正在分发
mDispatchingValue = true;
do {
// 一旦开始分发,标记颁发有效
mDispatchInvalidated = false;
// null与不是null的颁发逻辑有区别
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
// 遍历observer集合,并进行通知
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
// 这里就有讲究了,在下面会具体解释
} while (mDispatchInvalidated);
// 标记颁发结束
mDispatchingValue = false;
}
对于initiator是否为null的两种情况:
- null:会遍历绑定到
LiveData上的所有Observer,并进行通知。 - 不为null:只会通知传入的
initiator中的Observer
重点来了,这里为什么要用do-while,而不是简单的顺序逻辑。
- 当一个线程正在
dispatchingValue时,此时mDispatchingValue=true表示正在分发,mDispatchInvalidated=false表示此次分发有效。 - 现在第二个线程进来了,发现
mDispatchingValue=true,现在有另一个线程正在分发,又不能加进去,只能气愤地将mDispatchInvalidated=true,告诉第一个线程你现在的分发是无效的,因为我已经更改了mData。 - 第一个进程正在分发着,突然发现
mDispatchInvalidated=true,只能重来了,再次将mDispatchInvalidated=false,声明此次分发有效,重新进行分发了。
considerNotify
这个方法就是真正去通知每个观察者了。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// 此处是官方文档翻译
// 检查最新的状态b4调度。也许它改变了状态,但我们还没有得到事件。
// 我们还是先检查observer.active,以保持它作为活动的入口。
// 因此,即使观察者移动到一个活动状态,如果我们没有收到那个事件,我们最好不要通知一个更可预测的通知顺序。
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
- 首先
observer会检查自身mActive是否处于活跃状态。 - 有可能
mActive是处于活跃状态,但是因为还未收到生命周期更改的事件还没来得及改变,需要通过shouldBeActive主动去获取当前活跃状态。 - 每个新的观察者的
mLastVersion初始化为-1,如果发现mLastVersion小于LiveData的version,就会知道当前数据不是最新的,需要进行通知,这样就调用了onChanged方法。
postValue
因为setValue只能在主线程上进行调用,postValue则可以在子线程上调用。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
- 定义一个
postTask,判断是否要更新。 - 加个同步锁,存在多个子线程同时调用
postValue的情况。 - 通过判断更新的值是否发生变化来对
postTask赋值。- 第一次
mPendingData==NOT_SET一定为true,之后都会false。 - 因为在
Runnable中更新完后会将mPendingData重新赋值为NOT_SET,这样就会导致多次调用postValue只有最后一个值才有效的原因。
- 第一次
- 将
mPostValueRunnable提交给主线程执行。
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
mPostValueRunnable里面其实就是更新了value,因为已经在主线程了,直接调用了setValue。
取消订阅
removeObserver
@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);
}
- 首先会在
mObservers中移除对应的observer,并返回对应的wrapper。 - 如果
wrapper存在的话,调用其detachObserver方法,并将其状态变化设置为false。
比较特殊的方法
AlwaysActiveObserver
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
相比较LifecycleBoundObserver,AlwaysActiveObserver实现就简单多了,这个Observer会始终处于active状态,会接收一切事件,不会进行状态过滤。
observerForever
@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);
}
observerForever会生成一个AlwaysActiveObserver对象,始终会处active状态,后面的逻辑和observe差不多,唯一差别就是在wrpper只会调用一次activeStateChanged(true),后续状态始终为active,所以也无需监听了。
但是由此引出另一个问题,因为没有监听生命周期,无法自动对observer进行自动取消订阅,需要对此种observer进行手动取消订阅。
MediatorLiveData
MediatorLiveData继承于MutableLiveData,至于MutableLiveData的实现特别简单,仅仅是调用父类的方法,而MediatorLiveData的作用就是结合多个LiveData,一起进行监听。
所以,MediatorLiveData有多个LiveData与其Observer对应的存储结构。
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
Source
用来绑定LiveData和Observer的类。
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;
}
// 将LiveData与Observer绑定
void plug() {
mLiveData.observeForever(this);
}
// 将LiveData与Observer取消绑定
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
Source本身就是一个Observer,可以订阅LiveData,也提供了相应的plug与unplug方法进行订阅与取消,实现的onChanged方法实际上是比较当前version与LiveData的version是否一致,不一致则数据发生了变化,通知mObserver进行变化。
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();
}
}
- 将
sourceLiveData与observer进行绑定,生成对应的Source对象。 - 后面就是判断存在与否和
mObserver对象的一致性。 - 如果
MediatorLiveData有active状态的observer,则会自动执行source.plug()。
因为初始化没有Observer处于active状态,那么对应的sourceLiveData被onChanged订阅,那么是在什么时候订阅的呢?
onActive
@CallSuper
@Override
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
当MediatorLiveData从inactive状态变为active状态时,会触发onActive方法,在此方法中会绑定所有的sourceLiveData和observer。
onInactive
@CallSuper
@Override
protected void onInactive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
当MediatorLiveData处于inactive状态时,则会取消所有绑定。
四、总结
感觉LiveData还是比较容易弄明白的,只要耐心看下代码,还是很快能看懂的。
PS:还是希望有人能给我的文章提下意见,希望我之后的更改能够提升一下文章质量。