LiveData 是 Google 推荐的基于观察者的数据持有者,可以认为是一个轻量级的RxJava。
一般来说不会单独使用,会和其他组件一起搭配,最常用的就是 ViewModel 了。

目录

1. 概述

1.1 什么是LiveData

官方定义:

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

简单可以理解为一个 ​​Observable​​ ,同时能够感知生命周期

如果搭配ViewModel,那么 ViewModel 就是 LiveData 的数据源,当数据更新后, LiveData 就会通知它的所有观察者。 与 RxJava 的方法不同的是, LiveData 并不是通知所有观察者,他只会通知处于 Active 状态的观察者,如果一个观察者处于 Paused 状态或 Destroyed 状态,那么它将不会受到通知。

1.2 为什么使用LiveData

  1. 解耦
  2. 避免内存泄漏

Activity、Service、Fragment可以安全的观察LiveData对象,而且不用在 onPaused 或者 onDestroy 方法中去解订阅。
一旦观察者恢复 resumed 状态, 它将会重新收到 LiveData 的最新数据。

2. 使用

这里省去导入流程,可以看 ​​Jetpack学习之 Lifecycle​

2.1 基本用法

LiveData 是一个抽象类, 它有一个比较简单又常用的实现类:​​MutableLiveData​​, 这里举个栗子:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val mutableLiveData = MutableLiveData<String>()
// 1
mutableLiveData.observe(this, Observer {
Log.d(TAG, "onChanged: $it")
})
// 2
mutableLiveData.postValue("Hi Noel~")
}
}

注释1:​​observe()​​​ 有两个参数,分别是 ​​LifecycleOwner​​​ 和 ​​Observer<T>​​​ 也就是被观察者。
Kotlin代码的lambda表达式省略掉了其实现方法体,也就是 ​​​onChanged(@Nullable final String s)​​ 方法,他能够在数据变化时,回调这个方法

注释2:​​postValue()​​ 会在主线程更新数据,这样就会得到打印的结果,如下所示:

Jetpack学习之 LiveData_数据


这里需要注意的是:

  • 将更新界面的LiveData对象存储在ViewModel中,而不是将其存储在Activity或Fragment中:
    (1)避免Activity或Fragment过于庞大,分离 ui 和数据
    (2)将LiveData实例与特定Activity实例分离开,使LiveData对象在配置更改后继续存在
  • 在onCreate方法中开始观察LiveData对象
    不要在onResume方法中进行调用​​​observe()​​​ ,因为会出现多次调用的问题。
    确保Activity或Fragment变为活跃状态后具有可以立即显示的数据,因为应用组件处于STARTED 状态,就会从它正在观察的​​​LiveData​​ 对象接收最新值
  • 当组件处于DESTROY状态时会自动取消订阅
  • 除了使用​​postValue()​​​,还可以使用​​setValue()​​,区别是后者必须在主线程调用。如果需要在子线程中更新 LiveData, 可以使用 postValue 方法。

2.2 更改 LiveData 中的数据

2.2.1 Transformations.map 方法

和 RxJava 一样,我们可以对数据分发到指定对象之前,给它map一下,转化成另一种数据,比如下面代码,LiveData 原数据是 Int 型, 通过 map 转化成 String 类型(或则任何数据):

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val mutableLiveData = MutableLiveData<Int>()
mutableLiveData.observe(this, Observer {
Log.d(TAG, "onChanged1: $it")
})

val transformationsLiveData = Transformations.map(
mutableLiveData
) { input ->
("$input)
}

transformationsLiveData.observe(this, Observer {
Log.d(TAG, "obChanged2: $it")
})
mutableLiveData.postValue(1)
}

2.2.2 Transformations.switchMap 方法

和 map 不同, switchMap返回的结果必须是一个 ​​LiveData​​ 数据,而且它可以通过一个 Boolean 值来选择监听对象

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

mutableLiveData1 = MutableLiveData()
mutableLiveData2 = MutableLiveData()
// 1
liveDataSwitch = MutableLiveData()

// 如果是true,选择监听1,否则监听2
val transformedLiveData = Transformations.switchMap(liveDataSwitch) {
if (it) mutableLiveData1 else mutableLiveData2
}

transformedLiveData.observe(this, Observer {
Log.d(TAG, "onChanged: $it")
})
liveDataSwitch.postValue(false)
mutableLiveData1.postValue("noel")
mutableLiveData2.postValue("bye")
}

注释1:创建一个 ​​MutableLiveData<Boolean>​​​ 来控制切换并复制给 liveDataSwitch
当 liveDataSwitch 的值为 true 时, 返回 mutableLiveData1, 否则返回 mutableLiveData2
这样最终输出的结果为2

2.2.3 MediatorLiveData合并数据源

​MediatorLiveData​​​ 继承自 MutableLiveData, 它的作用是可以收集多个 LiveData。 如果其中一个 LiveData 数据源发生变化,那么也会通知到 ​​MediatorLiveData​

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val mutableLiveData1 = MutableLiveData<String>()
val mutableLiveData2 = MutableLiveData<String>()
// 创建一个用于合并数据源的LiveData
val liveDataManager = MediatorLiveData<String>()

// 添加数据 LiveData1, 并监听其变化
liveDataManager.addSource(mutableLiveData1) {
Log.d(TAG, "onChanged 1: $it")
}

// 添加数据 LiveData2, 并监听其变化
liveDataManager.addSource(mutableLiveData2) {
Log.d(TAG, "onChanged 2: $it")
}

liveDataManager.observe(this, Observer {
Log.d(TAG, "onChanged Data: $it")
})

mutableLiveData1.postValue("i always like u")
liveDataManager.postValue("thank u")
}

打印结果:

Jetpack学习之 LiveData_ide_02

2.2.4 自定义LiveData

我们可以自定义一个 LiveData, 因为会有观察者来观察这个 LiveData, 所以观察者处于 STARTED 或者 RESUMED 时,LiveData 将会处于 Activity状态,这个时候通过实现 ​​onActive()​​​ / ​​onInactive()​​ 来通知观察者。

下面是个例子,我们设定一个可以变化的数据类:

class ExtStringLiveData private constructor() : LiveData<String>() {

companion object {
private const val TAG = "ExtStringLiveData"

private var sInstance: ExtStringLiveData? = null

@MainThread
fun get(): ExtStringLiveData? {
if (sInstance == null) {
sInstance = ExtStringLiveData()
}
return sInstance
}
}

// 观察者处于活跃状态, 则通知它
override fun onActive() {
Log.d(TAG, "onActive")
// 这里的数据是写死的, 在实际项目中, 可以以监听器不断输出数据
value = "if u find me again, i will with u again"
}

override fun onInactive() {
Log.d(TAG, "onInactive")
// 这里的数据是写死的, 在实际项目中, 可以以监听器不断输出数据
// 在这之后, 就不会再想观察者发送数据直到观察者恢复active状态, 所以这一里在更改数据就不会通知了
value = "because I'm starting to regret it"
}
}

然后在 MainActivity 去监听它:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

ExtStringLiveData.get()?.observe(this, Observer {
Log.d(TAG, it)
})
}

打印结果为:

Jetpack学习之 LiveData_数据_03


而在 LiveData 的 ​​onInactive()​​ 中更改的string数据, MainActivity 就打印不出来了。

3. 原理

3.1 LiveData 如何观察生命周期变化

因为组件都是通过调用 ​​LiveData.observe(LifecycleOwner, Observer<? super T>)​​​ 进行监听,所以了解 ​​Livecycle​​ 的同学肯定就知道了其中的奥秘。我们来看看它的源码吧:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
// 1
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// 2
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 3
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;
}
// 4
owner.getLifecycle().addObserver(wrapper);
}

注释1:如果当前声明周期是 ​​DESTORYED​​, 则拒绝注册

注释2:新建一个 ​​LifecycleBoundObserver​​ 实例,并传入相应参数

注释3:mObservers 的类型是 ​​SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers​​​,key是观察者,value是注释2中创建的对象。
在这个map中的​​​putIfAbsent​​​ 和 ​​put​​ 是有区别的,如果传入的 key 存在,就返回value,而不替换,如果 key 不存在,则添加进去,并返回null。

注释4:如果注释3的map中没有数据, 则调用 ​​Lifecycle.addObserver​​​,传入的是 ​​LivecycleBoundObserver​​。 看来这个类比较重要,我们有必要去了解它的构造和作用。

3.2 LiveData 的 observe 方法回调

来看看 ​​LivecycleBoundObserver​​ ,它是 LiveData 的内部类:

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull final LifecycleOwner mOwner;
...
@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;
// 1
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}

@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}

@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}

该类继承了 ​​ObserverWrapper​​​ 类,重写了 ​​shouldBeActive()​​ 方法, 它的作用是用来判断当前传入的组件是否是 Active的, Active状态包括 STARTED 、 RESUMED

该类还实现了 ​​LifecycleEventObserver​​​ 接口,当组件状态发生变化的时候, 会调用 ​​onStateChanged()​​​ ,当组件处于 DESTORYED 状态是,会调用 ​​removeObserver()​​​ 来移除 observer。
这也就是为什么,LiveData 不会给那些 Inactive 的组件发通知。

注释1: 调用父类的 ​​activeStateChanged()​​,我们来看看父类:

private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;

ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}

abstract boolean shouldBeActive();

boolean isAttachedTo(LifecycleOwner owner) {
return false;
}

void detachObserver() {
}

void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
// 1
dispatchingValue(this);
}
}
}

​ObserverWrapper​​​ 是一个抽象类,它包装了一个 Observer, ​​activeStateChanged​​​ 会看 传进来的状态是否和此前状态是否相同,不同则,则执行 ​​changeActiveCounter()​​​ ,来更新一下当前LiveData 观察者的活跃与非活跃的数量, 来决定调用 ​​onActive()​​​ 或 ​​onInactive()​

其次,如果当前是 Active 状态,则调用注释1的 ​​dispatchingValue()​​ 方法

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;
}

如果当前处于可分发状态, 则会调用 ​​considerNotify()​​ 方法:

private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}

if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 1
observer.mObserver.onChanged((T) mData);
}

即使是到了这里,也会一直在判断当前组件的状态,非常严格呢。

如果所有更新条件都满足,则会调用 Observer 的 ​​onChanged()​​ , 也就从这里回调出去了~

3.3 postValue 方法

我们来看看调用 ​​postValue()​​​ / ​​setValue()​​ 之后,LiveData 做了什么事情, 这里以 postValue 为例,来看看代码~

protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
// 1
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
// 2
setValue((T) newValue);
}
};

// 3
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
// 4
dispatchingValue(null);
}

注释1、2:做一个线程切换,切换到主线程中,并用线程安全的 ​​synchronized()​

注释3:确定当前线程是主线程,在非主线程中直接调用该方法会crash

注释4: 调用 ​​dispatchingValue​​​ ,之后就是 ​​considerNotify()​​ 来通知观察者啦~

3.4 总结

  • ​LiveData​​​ 基于观察者模式实现和​​LifecyclerOwner​​ 绑定后能感知生命周期
  • 只有处于活跃状态的 Owne r才会接收到数据变化的通知,Owner从非活跃状态变为活跃状态,会接收到新的数据通知
  • Owner进入DESTROY状态会自动 remove Observer,不会担心内存泄露问题,如果希望一直接收到通知,可以使用​​observeForever()​​方法
  • 主线程使用​​setValue()​​​ 、工作线程使用​​postValue()​​ 进行数据更新

参考文章

《Android进阶指北》Android Jetpack架构组件
​​​LiveData官方文档​