官网介绍LiveData的概念是这样的:
LiveData
是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
归类的说,它有三个特点:
1、它是一个数据存储器类,能持有数据;
2、它可被观察者观察,当存在观察者时,它的数据变化会通知到观察者;
3、它能感知应用组件的生命周期;
它的上面这些特性,结合在一起,有以下的优势:
1、界面数据根据LiveData的数据而变化,数据始终保持最新状态
LiveData 遵循观察者模式。当生命周期状态或者本身数据发生变化时。会通知到相应的观察者。
如果生命周期从活跃状态变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
2、不会发生内存泄露、不会因 Activity 停止而导致崩溃、不再需要手动处理生命周期
通常的做法,是向LiveData中传入Lifecycle。当LiveData绑定Lifecycle后,LiveData的数据只会在组件生命周期的onStart后,才会被组件感知,当组件的生命周期到了onDestroy后,会在LiveData内部移除观察,不再接受数据。因此不会发生泄漏、也不需要手动处理生命周期,当然也不会因此导致activity的崩溃。
3、封装后的LiveData,可做为EventBus、RxBus的替代。可以很方便的提供数据传递以及项目中的响应式编程。
您可以使用单例模式封装 LiveData
,以便在应用中使用它。
(1)网络数据的获取,通过LiveData获取网络信息
,然后任何观察者只需观察 LiveData对象,都
能感知到数据变化
(2)本地数据的传递。将需要传递的数据用LiveData修饰,在多个页面间,观察者观察同一个LiveData对象。当某个页面上通过修改LiveData的对象时,其他观察者得到通知,实现数据传递。
第一种方式,如果是新工程,可以直接在创建工程时,在android studio中勾选androidx选项,会自动带入如下依赖即可。
implementation 'androidx.appcompat:appcompat:1.1.0'
第二种方式,如果是旧工程升级,可以在工程的build中,添加以下依赖:
def lifecycle_version = "2.2.0"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
根据前面提到的LiveData的三个特性,LiveData持有数据、可被观察、感知生命周期,我们分别说明
(1)持有数据,是一个数据存储类。
LiveData本身是一个抽象类,并且是顶层类。在android中的定义是这样的:
public abstract class LiveData{}
抽象类,我们无法直接使用,android为此也给我们提供了一个可用的LiveData的继承类:MutableLiveData,就是可变的LiveData。它的结构简单,也是我们日常用的最多的LiveData的实现类,如下:
public class MutableLiveData extends LiveData {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
MutableLiveData提供一个泛型,供传入对象类型,在经过posValue或者setValue后,LiveData中将会把该对象赋值给mData。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
mData是LiveData的一个局部变量,所以此时,LiveData是一个数据存储类。
(2)LiveData可被观察
LiveData提供了一类方法:observe,包括observe和observeForever。这个方法供外部传入观察者,当LiveData数据发生变化或者LiveData绑定的组件生命周期发生变化的时候,会通过observe的回调方法,通知观察者。
其中observe方法的入参中是一个含有生命周期的LifecycleOwner型组件对象和观察者本身,所以使用该方法订阅观察,会与组件的生命周期相关。
//observe方法订阅,与生命周期相关
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
....
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
owner.getLifecycle().addObserver(wrapper);
}
observeForever方法的入参只有观察者本身,不与生命周期关联。
//observeForever方法与生命周期无关
public void observeForever(@NonNull Observer super T> observer) {
...
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
wrapper.activeStateChanged(true);
}
(3)感知组件生命周期
这个就是通过observe方法订阅而来的功能。方法中传入LifecycleOwner,并将该观察者observer添加到了owner.getLifecycle()中。当owner的生命周期发生改变时,会调用LifecycleBoundObserver这个包装类的onStateChanged方法。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer){
super(observer);
mOwner = owner;
}
...
//组件生命周期发生变化时,会调用该方法
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//该方法会执行后续的observer的onChange回调
activeStateChanged(shouldBeActive());
}
...
}
原理分析,我们从LiveData给我们的入口开始。LiveData对外提供的方法,我们用到的有设置数据的postValue、setValue以及订阅的observe类型方法。
这里将通过三条路线,来分析LiveData的实现:1、postValue/setValue 2、observe 3、生命周期变化
由简入难,先从MutableLiveData的postValue开始:
(1)postValue在MutableLiveData中调用父类postValue方法。过程如下方所示:
//postValue任务
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
//锁
synchronized (mDataLock) {
//将临时数据传给newValue
newValue = mPendingData;
//mPendingData恢复初始值,等待下一次的postValue任务
mPendingData = NOT_SET;
}
//noinspection unchecked
//最终通过setValue设置内容
setValue((T) newValue);
}
};
...
protected void postValue(T value) {
//标识是否有post的runnable在执行,首次默认是false
boolean postTask;
//锁,保证postValue设置的内容的顺序性
synchronized (mDataLock) {
//mPendingData初始值就是NOT_SET,当mPendingData == NOT_SET时,表示正在执行
//postValue
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
//当此时,如果有其他postValue执行到此处,因为前面赋值mPendingData = value,postTask为
//false,阻塞执行。可以在端上同一时间,发起100笔postValue实验,能够执行后续runnable的将不
//足100次
if (!postTask) {
return;
}
//将postValue的runnable放到主线程执行
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
(2)postValue最终执行的还是setValue方法,setValue方法就是在主线程上,设置内容。
@MainThread
protected void setValue(T value) {
//限制只有主线程可以使用setValue,否则报错
assertMainThread("setValue");
//数字累加1
mVersion++;
//实际设置内容
mData = value;
//如有观察者,通过下方语句会触发回调
dispatchingValue(null);
}
(3)dispatchingValue方法如何触发回调
//ObserverWrapper入参是针对Observer的一个装饰包装,此时传入null
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//(1)控制状态
//mDispatchingValue 默认为false,表示未开始分发。
//此处添加该判断,是为了判断分发过程中,是否有新的分发请求进入
if (mDispatchingValue) {
//如在下方的分发事件执行过程中,有新的请求进入,则将mDispatchInvalidated(分发无效标
//识)置为true,会让下发的分发循环重新执行,重新分发一次新的数据
mDispatchInvalidated = true;
return;
}
//(2)分发
//分发状态置为true
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//此时initiator为null,执行遍历分发操作
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//实际的分发任务在此处执行
considerNotify(iterator.next().getValue());
//如果分发过程中,有新的请求调用了dispatchingValue方法,分发无效标识
//mDispatchInvalidated会在前面被置为true,跳出for循环,且此时while的条件为
//真,会重新执行do..while循环,重新将最新的数据分发下去
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
//分发任务全部执行完毕,则恢复默认值
mDispatchingValue = false;
}
(4)实际分发任务执行considerNotify
private void considerNotify(ObserverWrapper observer) {
//当观察者不存在或者未激活时,不做操作
if (!observer.mActive) {
return;
}
//当观察者不处于活动时,不发生回调
if (!observer.shouldBeActive()) {
//更新livedata内部的某些状态
observer.activeStateChanged(false);
return;
}
//版本判断
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
//回调数据
observer.mObserver.onChanged((T) mData);
}
到此,postValue与setValue的流程就告一段落。在最后的数据回调前,存在判断观察者是否存在,如不存在是不会发生回调的。
因此,这就要求我们需要给LiveData添加观察者。
以上是我们postValue与setValue流程告一段落,那么后续就来看一下observer是如何注册到LiveData中
(5)观察者observer的添加
在页面上给LiveData添加观察者,调用到LiveData的observe方法
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
//主线程限定
assertMainThread("observe");
//组件的生命周期如果是DESTROYED,直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//observer包装类,绑定组件与观察者
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//判断该观察者是否已存在
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//同一个observer 不能添加到不同的组件的生命周期中
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//将observer包装类,添加到组件的生命周期
owner.getLifecycle().addObserver(wrapper);
}
该方法传入LifecycleOwner的实现(一般情况下就是activity、fragment或者service)以及观察者observer-->判断是否在主线程-->如果是主线程,判断生命周期是否处于DESTROYED,如果不是则继续-->将owner与observer传入装饰包装类LifecycleBoundObserver中-->最后把这个observer包装类添加到组件的生命周期上。
下方式包装类的具体内容:
//GenericLifecycleObserver 接口是与传入的LifecycleOwner中的生命周期相对的
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
//判断此时的生命周期是否已处于STARTED后(也就是onStart后)
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//当组件的生命周期发生变化时,会主动回调该方法
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//生命周期销毁时,移除该观察者
removeObserver(mObserver);
return;
}
//生命周期变化,且非DESTROYED时,继续操作
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
以上这个LifecycleBoundObserver类,做了LifecycleOwner与observer做了绑定。当传入的组件生命周期变化,触发onStateChanged该方法。至此,前面提到的三条路线已经解析完成。这个就是LiveData的主要流程。
LiveData源码解析中,有哪些内容是你需要注意的?
(1)postValue中,为什么要有mPendingData?
postValue在传输数据的过程中,会经过两段操作。mPendingData作为临时存储数据的变量,是为了保证postValue多次、同 时被调用时的线程安全。
(2)对一个LiveData数据,同时做setValue与postValue,结果会是如何?
如果再同一时刻,对同一LiveData数据,做了setValue与postValue操作。最终页面刷新的数据,会是postValue中的数据。此 处注意不要这么操作。
(3)setValue/postValue过程中的dispatchingValue的逻辑巧用。
两个标识mDispatchingValue与mDispatchInvalidated,在入口判断与do...while中的循环逻辑,对分发过程中有新的数据需要 分发时,做了一次重新分发。
(4)onActive 与 onInactive的调用时机是什么样的?
onActive是在观察者从0到1的情况下,被调用。onInactive是在观察者从1到0的情况下被调用。
(5)observeForever与observe的区别是什么?
observeForever与生命周期无关。当使用该方法添加观察者后,不会与生命周期相关,如果无需使用的时候,需要手动 remove。这与通常的观察者模式是类似的。
(6)为什么LiveData会带有粘性特制?
假设在activity1中,有定义LiveData变量a,此时你并没有在该页面添加观察者,而是在activity2的onCreate中添加观察者。
当你在activity1,setValue或者postValue后,跳转到activity2,你会发现activity2中的观察者的回调起效了。
这就是类似EventBus的粘性事件,为什么会这样?仔细看源码,你会发现因为当你打开activity2,并且添加了观察者时,符合
了:生命周期变动 并且 observer.mLastVersion < mVersion ,引发了onChange。
如果不需要粘性事件,有两种方式:1、反射方式,在每次observe的时候,设置observer.mLastVersion = mVersion,这样首 次observe将不会再回调。2、YourLiveData继承LiveData,重写observe方法,并observer.mLastVersion = mVersion,在程序 中使用你自己的YourLiveData。
总结的说:当你将一个对象用LiveData包装后,你可以通过postValue/setValue修改该对象的值,该值会反应在与LiveData的观察者上。以此可以实现数据驱动UI。LiveData中含有生命周期的判断,会在合适的时候,判断是否解除观察者订阅,避免内存泄漏等。这是针对android的一个很好的架构组件!后续将介绍如何使用。