了解LiveData
前段时间学习ViewModel的时候就提到LiveData,单独的ViewModel并不能发挥它的全部“实力”。所以需要继续学习LiveData,善于实践结合ViewModel完成MV的解耦。
1、LiveData简介
LiveData组件是什么?有哪些优势?这些在Google的官网都能找到答案。详见LiveData Overview
1.1、介绍
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
LiveData抽象类有几个实现子类,分别是:MutableLiveData、MediatorLiveData等。
①MutableLiveData继承自LiveData,暴露了修改value的方法,因为LiveData中的修改值方法权限是protected。
②MediatorLiveData又继承自MutableLiveData类,合并多个LiveData源,在任何原始LiveData源对象改变后,MediatorLiveData对象的Observer会被触发。
并且可以借助Transformations转换或修改LiveData返回的数据,详见Transform LiveData。
1.2、优势
使用LiveData有以下优势,这些优势解决的正是让Android开发者头疼的地方:
①不会发生内存泄漏
②不会因 Activity 停止而导致崩溃
③不再需要手动处理生命周期
④数据始终保持最新状态
⑤共享资源
1.3、引入依赖
在build.gradle中加上使用LiveData组件所需的相关依赖,更多Lifecycle组件详见Jetpack > Libraries > Lifecycle。
dependencies {
...
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
...
}
2、LiveData简单用法
LiveData使用起来也很方便,主要一下三步。一般LiveData放在ViewModel中使用。
①创建保存特定数据类型的LiveData实例;
②创建Observer对象,作为参数传入LiveData.observe()方法添加观察者;
③更新Livedata对象存储的数据;
2.1、创建LiveData
在ViewModel中创建LiveData<T>对象持有数据,用到的时候再初始化。关于ViewModel的用法详见ViewModel视图与数据的桥梁。
public class UserModel extends ViewModel {
private MutableLiveData<String> userName;
public MutableLiveData<String> getUserName() {
if (null == userName) {
userName = new MutableLiveData<>();
}
return userName;
}
}
2.2、添加观察者
在UI层通过ViewModel实例获取其中持有的LiveData数据对象:
UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
MutableLiveData<String> name = userModel.getUserName();
2.3、添加观察者
LiveData其实就是观察者模式。它的关键就是这步,在UI层给LiveData对象添加观察者,当数据变化时会通过onChanged(T t)回调方法通知观察者,参数t就是变化的值。有两种添加模式
①observe(LifecycleOwner owner,Observer<? super T> observer)
name.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "observe " + s);
}
});
②observeForever(Observer<? super T> observer)
name.observeForever(new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "observeForever " + s);
}
});
使用该方法,一定要注意在不需要的时候需要手动调用removeObserver(final Observer<? super T> observer)方法移除观察者。
2.4、更新数据
获取数据可以调用LiveData中的getValue()方法。只有MutableLiveData类型的对象才可以更新其中的数据,有两种方法:
①setValue(T value):必须在主线程调用该方法
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
②postValue(T value):可以在子线程中调用,内部通过Handler在主线程中更新数据。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
2.5、活跃态、非活跃态
我们还可以自定义LiveData,重写onActive()和onInactive()方法,当LiveData被添加观察者时进行初始化或注册操作,当LiveData没有观察者被暂时不被观察的时候就可以移除资源。
public class MyLiveData extends LiveData {
@Override
protected void onActive() {
super.onActive();
//当活动观察者的数量从0更改为1时调用。
}
@Override
protected void onInactive() {
super.onInactive();
//当活动观察者的数量从1更改为0时调用。
}
}
3、源码分析
先会用,再看其中的实现原理。LiveData主要涉及到三个技术要点:注册观察者、观察者的回调流程、生命周期相关处理。关于ViewModel的源码另见ViewModel视图与数据的桥梁。
3.1、添加观察者
通过前面的简单使用,了解到给LiveData添加观察者使用的是observe()或observeForever()方法。来看看observe()方法,第一个参数LifecycleOwner一般就是实现了LifecycleOwner接口的Activity或者Fragment。
@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);
}
内部将传入的LifecycleOner和Observer实例用LiveData中的内部类LifecycleBoundObserver包装起来。LifecycleBoundObserver包装了观察者和被观察者,并且实现了LifecycleEventObserver(LifecycleObserver)接口(涉及到Lifecycle,详见Lifecycle生命周期感知组件)。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
回到observe()方法中,有一步判断,不能将同一个观察者设置给不同的Lifecycle实例。也就是传入的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;
}
最后一步,将包装好的观察者添加给LifecycleOwner监听生命周期的变化。
...
owner.getLifecycle().addObserver(wrapper);
}
3.2、更新通知
当我们更新LiveData中的数据的时候,是如何回调给注册的观察者呢?来看看更新value的方法setValue(T value):
@MainThread
protected void setValue(T value) {
//必须在主线程调用setValue(T value)方法
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
setValue(T value)操作涉及到几个全局变量:
private volatile Object mData;
// 当setData被调用时,设置挂起的数据,实际的数据交换发生在主线程上
@SuppressWarnings("WeakerAccess") /* synthetic access */
volatile Object mPendingData = NOT_SET;
private int mVersion;
接着调用了dispatchingValue()方法,注意这里传的参数是null。这一系列的操作都在主线程,否则子线程操作容易涉及到多线程同步的问题,复杂化!
@SuppressWarnings("WeakerAccess") /* synthetic access */
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,就只更新这个观察者。如果为null,就遍历通知在mObservers中注册的所有观察者。通过considerNotify(ObserverWrapper observer)方法
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);
}
最后一行代码,就可以看到调用了Observer的onChange(T t)方法,回调通知观察者,通样是在UI主线程,不能做耗时操作。另一个更新值的方法postValue(T value)类似,之所以可以在子线程调用,是因为内部封装了更新值的任务,通过主线程的MainHandler执行。
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
3.3、生命周期
当Activity、Fragment生命周期发生变化的时候,LiveData是如何感知的呢?答案就在刚刚提到的LifecycleBoundObserver包装类中:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
之前学习Lifecycle的时候知道Activity的生命周期发生变化的时候会回调给LifecycleEventObserver,回调其中的onStateChanged(LifecycleOwner source,Lifecycle.Event event)方法,该方法在LifecycleBoundObserver中的实现如下:
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
当Activity生命周期DESTORYED时,会移除观察者,调用的是LiveData的方法removeObserver(Observer<? super T> observer)
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);
}
detachObserver()将会从LifecycleOwner中移除该包装类观察者对象自身:
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
并且调用activeStateChanged(boolean newActive)设置不再激活,该方法是ObserverWrapper包装类中的方法。
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
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);
}
}
在这里可以看到onActive()和onInactive()空方法回调,当首次给LiveData注册观察者,以及移除全部观察者时分别回调。
最后,从LifecycleBoundObserver中的shouldBeActive()方法,我们可以看到LiveData只有当Activity或Fragment的Lifecycle状态处于STARTED、RESUME才会激活状态。
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
但是对于通过observeForever(Observer<? super T> observer)方法注册的则不同,使用的是AlwaysActiveObserver类包装,其中该方法始终返回true,也就是不管Activity生命周期处于什么状态,都会回调通知前台更新数据,除非手动移除观察者!
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
参考资料:
Android Developers > Guides > LiveData Overview
Jetpack > Libraries > Lifecycle
带你深入了解官方架构组件LiveData
Android应用结构之LiveData
LiveData的工作原理
LiveData
LiveData的用法