前言
LiveData 组件是 Jetpack 推出的基于观察者的消息订阅/分发组件,具有宿主(Activity、Fragment)生命周期感知能力,这种感知能力可确保 LiveData 仅分发消息给处于活跃状态的观察者,即只有处于活跃状态的观察者才能收到消息,并在 Lifecycle 处于无效状态(DESTROYED)时自动移除数据监听行为,从而避免常见的内存泄露和 NPE 问题(观察者模式)
LiveData 的消息分发机制,是以往的 Handler、EventBus、RxjavaBus 无法比拟的,它们不会顾及当前页面是否可见,一股脑的有消息就转发。导致即便应用在后台页面不可见的情况下还在做一些无用的工作抢占资源
Google LiveData 介绍
LiveData引入工程
implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
LiveData核心类和方法介绍
MutableLiveData
在使用 LiveData 的做消息分发的时候,需要使用这个子类。之所以这么设计,是考虑到单一开闭原则,只有拿到 MutableLiveData
对象才可以发送消息,LiveData
对象只能接收消息,避免拿到 LiveData
对象时既能发消息也能收消息的混乱使用 (设计原则:职责单一)
@SuppressWarnings("WeakerAccess")
public class MutableLiveData extends LiveData {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
MediatorLiveData
可以统一观察多个 LiveData
发射的数据进行统一的处理。同时也可以做为一个 LiveData
,被其他 Observer
观察
public class MediatorLiveData extends MutableLiveData {
private SafeIterableMap, Source>> mSources = new SafeIterableMap<>();
//添加观察者
@MainThread
public void addSource(@NonNull LiveData source, @NonNull Observer super S> onChanged) {
//将被观察者 和观察者 包装成一个 Source对象 添加到map中 且只能添加一次
Source 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();
}
}
@MainThread //移除被观察者 并移除观察者监听
public void removeSource(@NonNull LiveData toRemote) {
Source> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override //活动状态 统一为所有Source添加观察者
protected void onActive() {
for (Map.Entry, Source>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override //活动状态 统一为所有Source移除观察者监听
protected void onInactive() {
for (Map.Entry, Source>> source : mSources) {
source.getValue().unplug();
}
}
private static class Source implements Observer {
final LiveData mLiveData;
final Observer super V> mObserver;
int mVersion = START_VERSION;
Source(LiveData liveData, final Observer super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
//liveData添加 观察者
void plug() {
mLiveData.observeForever(this);
}
//liveData移除 观察者
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
统一观察多个 LiveData
发射的数据进行统一的处理
//创建两个长得差不多的LiveData对象
LiveData liveData1 = new MutableLiveData();
LiveData liveData2 = new MutableLiveData();
//再创建一个聚合类MediatorLiveData
MediatorLiveData liveDataMerger = new MediatorLiveData<>();
//分别把上面创建LiveData 添加进来。
liveDataMerger.addSource(liveData1, observer);
liveDataMerger.addSource(liveData2, observer);
Observer observer = new Observer() {
@Override
public void onChanged(@Nullable Integer s) {
titleTextView.setText(s);
}
//一旦liveData1或liveData2发送了新的数据 ,observer便能观察的到,以便 统一处理更新UI
Transformations
Transformations
是用于 LiveData
类的转换。
可以使用转换方法在观察者的整个生命周期中传递信息。 除非观察者观察返回的 LiveData 对象,否则不计算转换。由于转换是延迟计算的,因此与生命周期相关的行为将隐式传递,而无需其他显式调用或依赖项
Google Transformations 介绍
public class Transformations {
private Transformations() {
}
/**LiveData userLiveData = ...;
*LiveData userFullNameLiveData =
*Transformations.map(
* userLiveData,
* user -> user.firstName + user.lastName);
})*/
//将主线程上的给定函数应用于 LiveData 数据源发出的每个值,
//然后返回 LiveData,来发出结果值。给定的函数 func 将在主线程上执行
@MainThread
@NonNull
public static LiveData map(
@NonNull LiveData source,
@NonNull final Function mapFunction) {
//监听 source 的变化 获取 source 的值 在通过 mapFunction 返回新的值 set给 result
final MediatorLiveData result = new MediatorLiveData<>();
result.addSource(source, new Observer() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}
@MainThread
@NonNull
public static LiveData switchMap(
@NonNull LiveData source,
@NonNull final Function> switchMapFunction) {
//监听 source 的变化 获取 source 的值
//在通过 switchMapFunction 返回新LiveData 再监听此 LiveData 的值该变 set给result
final MediatorLiveData result = new MediatorLiveData<>();
result.addSource(source, new Observer() {
LiveData mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData newLiveData = switchMapFunction.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
@MainThread
@NonNull
public static LiveData distinctUntilChanged(@NonNull LiveData source) {
//每次不同的值该变 才能触发 outputLiveData onChanged
final MediatorLiveData outputLiveData = new MediatorLiveData<>();
outputLiveData.addSource(source, new Observer() {
boolean mFirstTime = true;
@Override
public void onChanged(X currentValue) {
final X previousValue = outputLiveData.getValue();
if (mFirstTime
|| (previousValue == null && currentValue != null)
|| (previousValue != null && !previousValue.equals(currentValue))) {
mFirstTime = false;
outputLiveData.setValue(currentValue);
}
}
});
return outputLiveData;
}
}
Transformations用例介绍 参考:Transformations
class UserViewModel extends AndroidViewModel {
//map
LiveData userLiveData = ...;
//返回一个新的LiveData
LiveData userFullNameLiveData =
Transformations.map(
userLiveData,
user -> user.firstName + user.lastName);
});
//switchMap
MutableLiveData nameQueryLiveData = ...
LiveData> getUsersWithNameLiveData() {
return Transformations.switchMap(
nameQueryLiveData,
name -> myDataSource.getUsersWithNameLiveData(name));
}
void setNameQuery(String name) {
this.nameQueryLiveData.setValue(name);
}
}
LiveData事件分发实现原理分析
LiveData构造方法
public abstract class LiveData {
//观察者集合
private SafeIterableMap, ObserverWrapper> mObservers =
new SafeIterableMap<>();
//事件改变计数器
static final int START_VERSION = -1;
static final Object NOT_SET = new Object();
int mActiveCount = 0;
// volatile 关键字
private volatile Object mData;
private int mVersion;
volatile Object mPendingData = NOT_SET;
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;//事件计数器 加1
}
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
}
观察者注册
observe
注册时,可以主动跟宿主生命周期绑定,不用反注册(当目标生命周期处于死亡状态会调用解注册函数)
@MainThread //主线程限制
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
//断言,这个方法只能在主线程调用,observeForever也是。
assertMainThread("observe");
//获取宿主的状态 死亡状态就直接退出
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//把注册进来的observer包装成 一个具有生命周边边界的观察者
//它能监听宿主被销毁的事件,从而主动的把自己反注册,避免内存泄漏
//此时观察者是否处于活跃状态就等于宿主是否可见
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;
}
//向Lifecycle 添加观察者
owner.getLifecycle().addObserver(wrapper);
}
LifecycleBoundObserver
观察者对象
PS:看过Lifecycle源码的话 就会发现这种添加观察者写法的方式非常的雷同
//生命周期事件分发接口
public interface LifecycleEventObserver extends LifecycleObserver {
void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
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() {
//使用observer方法注册的观察者都会被包装成LifecycleBoundObserver
//观察者是否活跃就等于宿主 的状态是否大于等于STARTED,
//如果页面当前不可见,你发送了一条消息,此时是不会被分发的,可以避免后台任务抢占资源,当页面恢复可见才会分发。
//注意:如果使用observerForever注册的观察者,
//会被包装成AlwaysActiveObserver,它的shouldBeActive一致返回true.即便在页面不可见也能收到数据
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//在这里如果监听到宿主被销毁了,则主动地把自己从livedata的观察者中移除掉
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);//宿主处于死亡状态时 就在map中移除观察者
return;
}
//说明宿主的状态发生了变化,此时会判断宿主是否处于活跃状态
activeStateChanged(shouldBeActive());
}
@Override //判断是否为同一个被观察者(activity 或者 fragment)
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {//被移除map时 真正调用移除观察者的是这里
mOwner.getLifecycle().removeObserver(this);
}
}
ObserverWrapper
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;//-1 事件分出次数
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;
//初次添加观察者时为0
boolean wasInactive = LiveData.this.mActiveCount == 0;
//如果此时有且只有一个活跃的观察者则触发onActive
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
//可以做一些初始化工作
onActive();
}
//没有任何一个活跃的观察者则触发onInactive
//利用这个方法被触发的时机,可以做很多事,比如资源释放等
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
//如果此时观察者处于活跃状态,下面就开始分发数据了
//请注意,这里传递了this = observer
if (mActive) {
dispatchingValue(this);
}
}
}
dispatchingValue
数据分发流程控制
//2个 boolean 值 类似于flag 开关 用于控制 数据分发时顺序控制
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {//true 说明 下面的数据分发流程还没走完
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) {// true 说明有新数据来了 这次数据下发已经没有意义了
break; //结束循环
}
}
}
} while (mDispatchInvalidated); //接着执行
mDispatchingValue = false;
}
considerNotify
数据真正分发的地方,需要满足三个条件
private void considerNotify(ObserverWrapper observer) {
//宿主不是活跃状态
if (!observer.mActive) {
return;
}
//判断宿主不是活跃状态 并且更改观察者的状态为false
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//此处判断观察者接收消息的次数是否大于等于 发送消息的次数
//但是observer被创建之初verison=-1
//如果此时LiveData已经发送过数据了。这里就不满足了,就出现黏性事件了,后注册的观察者收到了前面发送的消息。
// mLastVersion =-1 mVersion=1 ||>1
if (observer.mLastVersion >= mVersion) {
return;
}
//每分发一次消息,则把观察者和LiveData的version对齐,防止重复发送
observer.mLastVersion = mVersion;
//最后的数据传递
observer.mObserver.onChanged((T) mData);
}
setValue / postValue
事件更新发送
//可以在子线程执行
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//底层是通过Handler.post(runnable) 扔回主线程执行
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
//必须在主线程执行
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
//事件分发
dispatchingValue(null);
}
其他观察者:AlwaysActiveObserver
不用去关心宿主生命周期状态 任何时候 都能观察到数据的改变 关键在 shouldBeActive 任何时候都返回true 不去检查宿主生命周期状态
//不用去关心宿主生命周期状态 任何时候 都能观察到数据的改变
@MainThread
public void observeForever(@NonNull Observer super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
//添加到观察者结合
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer super T> observer) {
super(observer);
}
@Override//始终返回true
boolean shouldBeActive() {
return true;
}
}
//移除观察者
@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); //调用onInactive()做一些资源释放工作
}
//移除这个宿主中的所有观察者
@SuppressWarnings("WeakerAccess")
@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner) {
assertMainThread("removeObservers");
for (Map.Entry, ObserverWrapper> entry : mObservers) {
if (entry.getValue().isAttachedTo(owner)) {
removeObserver(entry.getKey());
}
}
}
LiveData总结
确保界面符合数据状态
LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 [Observer]对象并把最新数据派发给它。观察者可以在收到onChanged事件时更新界面,而不是在每次数据发生更改时立即更新界面。(分发过程有检查宿主(activity)生命周期的逻辑)不再需要手动处理生命周期
只需要观察相关数据,不用手动停止或恢复观察。LiveData 会自动管理Observer的反注册,因为它能感知宿主生命周期的变化,并在宿主生命周期的onDestory自动进行反注册。因此使用LiveData做消息分发不会发生内存泄漏数据始终保持最新状态
如果宿主的生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。支持黏性事件的分发
即先发送一条数据,后注册一个观察者,默认是能够收到之前发送的那条数据的-
共享资源
可以使用单例模式拓展 LiveData,实现全局的消息分发总线。美团LiveEventBus