LiveData
是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
如果观察者(由 Observer
类表示)的生命周期处于 STARTED
或 RESUMED
状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData
对象而注册的非活跃观察者不会收到更改通知。
您可以注册与实现 LifecycleOwner
接口的对象配对的观察者。有了这种关系,当相应的 Lifecycle
对象的状态变为 DESTROYED
时,便可移除此观察者。这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData
对象,而不必担心泄露(当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们)。
LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer
对象。您可以整合代码以在这些 Observer
对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。
观察者会绑定到 Lifecycle
对象,并在其关联的生命周期遭到销毁后进行自我清理。
如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
您可以使用单例模式扩展 LiveData
对象以封装系统服务,以便在应用中共享它们。LiveData
对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData
对象。如需了解详情,请参阅扩展 LiveData。
如果你的项目引入了androidx.appcompat:appcompat:***
包,默认LiveData已经引入
dependencies {
val lifecycle_version = "2.4.0-alpha02"
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
}
dependencies {
val lifecycle_version = "2.4.0-alpha02"
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata:$lifecycle_version")
}
class MyViewModel : ViewModel() {
val name = MutableLiveData()
private fun getName() {
name.value="数据内容"
}
}
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val viewModel = ViewModelProvider(this)[MyViewModel::class.java]
viewModel.getName().observe(this, Observer{ name ->
// update UI
})
}
}
我们知道 livedata 的使用很简单,它是采用观察者模式实现的
public interface Observer {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(T t);
}
LiveData包含两个用于添加数据观察者(Observer)的方法,分别是
生命周期安全的
两个方法的区别对于外部来说只在于是否提供了生命周期安全的保障。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
//限定只能在主线程调用 observe 方法
assertMainThread("observe");
//当 Lifecycle 已经处于 DESTROYED 状态时,此时进行 observe 是没有意义的,直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//根据传入参数构建一个新的代理 Observer
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//将 observer 作为 key,wrapper 作为 value 进行存储
//当 mObservers 不包含该 key 时,调用 putIfAbsent 会返回 null
//当 mObservers 已包含该 key 时,调用 putIfAbsent 不会存储 key-value,并会返回之前保存的 value
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
//走到此步,说明之前 LiveData 内部已经持有了 observer 对象,
//且该 observer 对象已经绑定了其它的 LifecycleOwner 对象
//此时直接抛出异常
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
//observer 之前已经传进来过了,此处直接返回
return;
}
owner.getLifecycle().addObserver(wrapper);
}
传入的LifecycleOwner
参数意味着携带了Lifecycle对象,LiveData内部就根据 Lifecycle的生命周期事件的回调变化在合适的时机进行数据通知,并在 Lifecycle对象处于DESTROYED状态时自动移除Observer,这也是LiveData避免内存泄漏的最重要的一个点。
上面的代码使用到了LifecycleBoundObserver
,它是抽象类ObserverWrapper的实现类。ObserverWrapper用于包装外部传进来的Observer对象,为子类定义好特定的抽象方法和共用逻辑,主要是提供了共用的状态分发函数。
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() {
//只有当 Lifecycle 的当前状态是 STARTED 或者 RESUMED 时
//才认为 Lifecycle 是处于活跃状态
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//LifecycleEventObserver 的实现方法
//当 Lifecycle 的生命周期状态发生变化时就会调用此方法
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//如果 Lifecycle 已经处于 DESTROYED 状态了,则主动移除 mObserver
//这就是 LiveData 可以避免内存泄露最重要的一个点
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
//移除 mObserver
mOwner.getLifecycle().removeObserver(this);
}
}
LifecycleBoundObserver的整个事件流程是这样的:
private abstract class ObserverWrapper {
//外部传进来的对 LiveData 进行数据监听的 Observer
final Observer super T> mObserver;
//用于标记 mObserver 是否处于活跃状态
boolean mActive;
//用于标记 Observer 内最后一个被回调的 value 的新旧程度
int mLastVersion = START_VERSION;
ObserverWrapper(Observer super T> observer) {
mObserver = observer;
}
//用于获取当前 Lifecycle 是否处于活跃状态
abstract boolean shouldBeActive();
//用于判断 mObserver 是否和 LifecycleOwner(即 Lifecycle)有绑定关系
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
//移除 mObserver
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
//判断当前 LiveData 所有的 Observer 是否都处于非活跃状态
boolean wasInactive = LiveData.this.mActiveCount == 0;
//更新 LiveData 当前所有处于活跃状态的 Observer 的数量
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
//如果 LiveData 处于活跃状态的 Observer 数量从 0 变成了 1,
//则回调 onActive 方法
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
//如果 LiveData 处于活跃状态的 Observer 数量从 1 变成了 0,
//则回调 onInactive 方法
onInactive();
}
if (mActive) {
//如果 mObserver 变成了活跃状态,则向其回调新值
dispatchingValue(this);
}
}
}
ObserverWrapper一共有两个子类:
LifecycleBoundObserver和AlwaysActiveObserver,两者的差别就在于是否和生命周期相绑定。
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
//限定只能在主线程调用 observe 方法
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
//会走到这一步,是因为之前已经先用该 observer 对象调用了 observe(LifecycleOwner,Observer)
//这里直接抛出异常
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
//如果之前已经添加过 observer 对象了的话,则直接返回
return;
}
//主动触发 activeStateChanged 函数,因为当前 LiveData 可能已经被设置值了
wrapper.activeStateChanged(true);
}
上面代码使用到了AlwaysActiveObserver,它也是抽象类ObserverWrapper的实现类,其shouldBeActive()返回值固定为true,意味着只要有数据变化都会进行回调。所以使用observeForever()函数一定要在过后主动移除Observer
,避免内存泄露和NPE。
更新LiveData的值的方法一共有两个,分别是:
setValue(T)函数被限定在只能主线程进行调用。
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
*
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
//更新当前 value 的版本号,即 value 的新旧程度
mVersion++;
mData = value;
dispatchingValue(null);
}
dispatchingValue()
函数设计得比较巧妙,用两个全局的布尔变量mDispatchingValue和mDispatchInvalidated就实现了新旧值判断、旧值舍弃、新值重新全局发布的逻辑。
//initiator 为 null 则说明需要遍历回调整个 mObservers
//initiator 不为 null 则说明仅回调 initiator 本身
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果当前正处于向 mObservers 发布 mData 的过程中(即 mDispatchingValue 为 true)
//则将 mDispatchInvalidated 置为 true,用于标明有新值到来,正在回调的值是已经过时的了
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
// 判断是否要将数据分发到指定的 ObserverWrapper
private void considerNotify(ObserverWrapper observer) {
//如果 observer 处于非活跃状态,则直接返回
if (!observer.mActive) {
return;
}
//此处判断主要是为了照顾 LifecycleBoundObserver
//由于 Lifecycle 有可能状态值 State 已经切换到了非活跃状态,但 LifecycleBoundObserver 还未收到事件通知
//所以为了避免意外情况,此处主动检查 observer 的活跃状态并判断是否需要更新其活跃状态
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//根据 observer 本部的 value 版本号 mLastVersion 来决定是否需要向其进行回调
//为了避免重复向某个 observer 回调值,所以此处需要判断下
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
*
* liveData.postValue("a");
* liveData.setValue("b");
*
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
*
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
postValue(T)函数不限定调用者所在线程,不管是主线程还是子线程都可以调用,因此是存在多线程竞争的可能性的,postValue(T)函数的重点 旧在于需要理解其从子线程切换到主线程之间的状态变化。
在mPostValueRunnable被执行前,所有通过postValue(T)函数传递的value都会被保存到变量mPendingData上,且只会保留最后一个
,直到mPostValueRunnable被执行后mPendingData才会被重置,所以使用 postValue(T) 函数在多线程同时调用或者单线程连续调用的情况下是存在丢值(外部的 Observer 只能接收到最新值)的可能性的。