本文目标
理解并掌握LiveData组件用法和原理
1.什么是LiveData
- LiveData组件是Jetpack推出的基于观察者的消息订阅/分发组件,具有宿主(
Activity
,Fragment
)生命周期感知能力,这种感知能力可确保LiveData
仅分发消息给处于活跃状态
的观察者,即只有处于活跃状态
的观察者才能收到消息 - LiveData的消息分发机制,是以往的
Handler
,EventBus
,RxjavaBus
无法比拟的,他们不会顾及到当前页面是否可见,一股脑的有消息就发送.导致即便应用在后台,页面不可见,还在做一些无用的绘制,细心的小伙伴可以发现微信消息列表是在可见状态时才会更新列表最新消息的
活跃状态:
Observer
所在宿主处于STARTED
,RESUMED
状态
2.基本用法
-
MutableLiveData
我们在使用LiveData
的做消息分发的时候,需要使用到这个子类.其实MutableLiveData
只是继承了LiveData
,然后重写了postValue(T)
和setValue(T)
,把父类的protected
改成了public
,之所以这么设计,是考虑到单一开闭原则,只有拿到MutableLiveData
对象才可以发送消息,LiveData
对象只能接受消息,避免拿到LiveData
对象时既能发消息也能收消息的混乱使用.
public class MutableLiveData<T> extends LiveData<T> {
/**
* Creates a MutableLiveData initialized with the given {@code value}.
*
* @param value initial value
*/
public MutableLiveData(T value) {
super(value);
}
/**
* Creates a MutableLiveData with no value assigned to it.
*/
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
-
MediatorLiveData
1.可以统一观察多个LiveData
的发射的数据进行统一处理
2.同时也可以作为一个LiveData
,被其他Observer
观察
//创建两个长的差不多的LiveData对象
MutableLiveData<String> liveDat1=new MutableLiveData<>();
MutableLiveData<String> liveDat2=new MutableLiveData<>();
//在创建一个聚合类MediatorLiveData
MediatorLiveData<String> allLiveData=new MediatorLiveData<>();
//可以观察到
Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i("yd","onChanged刷新一次");
}
};
//分别把上面创建的两个LiveData对象添加进来
allLiveData.addSource(liveDat1,observer );
allLiveData.addSource(liveDat2,observer );
//一旦liveDat1或liveDat2发送了新的数据,observer便可以观察到,以便统一处理更新UI
3.黏性消息实现原理
- 黏性消息分发流程,即新注册的
Observer
也能接受到前面发送的最后一条数据,通俗来说就是先发射事件,然后在注册观察者,照样能收到
我们从LiveData
的public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
方法看起,来直接上源码
public abstract class LiveData<T> {
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//1,把observer包装成 LifecycleBoundObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//存到map集合中,有消息就去分发
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;
}
//3.把上面包装后的对象 注册到 `Lifecycle`之中
owner.getLifecycle().addObserver(wrapper);
}
}
该方法主要做了两件事
- 1.把
observer
包装成LifecycleBoundObserver
具有生命周期边界的观察者,也就是说宿主状态是STARTED
或RESUMED
才会接受数据,其他状态不接受数据 - 2.存到map集合中,有消息就去分发,key:我们传进来的
Observer
对象,value:包装成的LifecycleBoundObserver
对象 - 3.把上面包装后的对象 注册到
Lifecycle
之中,这里就是LiveData
利用Lifecycle
的地方,能感知生命周期的关键地方,初次注册,宿主每次生命周期的变化都会回调onStateChanged
方法,也就是说会回调LifecycleBoundObserver
的onStateChanged()
方法,
来我们看下LifecycleBoundObserver
类
public abstract class LiveData<T> {
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//宿主的状态是否处于活跃状态,其实就是判断宿主是否是STARTED或RESUMED
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//1.宿主被销毁事件,则从liveData移除该观察者,流程结束
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//2.如果宿主的状态为活跃状态STARTED,RESUMED,则分发最新数据到每个观察者
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
}
在onStateChanged(Event event)
方法中,
- 1.宿主被销毁事件,则从liveData移除该观察者,流程结束
- 2.
activeStateChanged(shouldBeActive());
这行代码,如果宿主的状态是活跃的为STARTED
,RESUMED
,则分发最新数据到每个观察者,
具体是如何进行的我们可以追进去看下
public abstract class LiveData<T> {
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
//没有任何一个观察者处于活跃状态
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
//1.当且仅当有一个观察者的时候才会触发
if (wasInactive && mActive) {
onActive();
}
//2.如果没有任何一个活跃的观察者,则会触发
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
//3.如果宿主的状态是活跃的为STARTED,RESUMED,则分发最新数据到每个观察者,
if (mActive) {
dispatchingValue(this);
}
}
}
}
- 1.做一些判断,当且仅当有一个观察者的时候才会触发
onActive()
方法,该方法是空方法(官方留给我们的口子) - 2.如果没有任何一个活跃的观察者,则会触发
onInactive();
方法,该方法是空方法(官方留给我们的口子) - 3.如果宿主的状态是活跃的为STARTED,RESUMED,则分发最新数据到每个观察者,触发
dispatchingValue(this);
继续往下追
public abstract class LiveData<T> {
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//如果传入的对象不为空,则直接调用分发事件方法
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//为空,说明是从 setValue方法进来,的需要for循环遍历一遍,然后把事件分发给观察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//该行代码中真正的分发了事件
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
}
- 1.如果传入的对象
initiator
不为空,则直接调用分发事件方法 - 2.如果传入的对象
initiator
为空,说明是从setValue
方法进来,的需要for循环遍历一遍,然后把事件分发给观察者
不论对象initiator
是否为空,最后都会调用considerNotify(iterator.next().getValue());
这行代码才是真正的去分发事件
public abstract class LiveData<T> {
private void considerNotify(ObserverWrapper observer) {
//1.如果观察者所在的宿主不活跃了,不分发
if (!observer.mActive) {
return;
}
//判断观察者是否处于活跃状态
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//2.如果observer.mLastVersion >= LiveData的mVersion,不分发
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//3.分发数据
observer.mObserver.onChanged((T) mData);
}
}
上面的considerNotify(ObserverWrapper observer)
方法里面会做一些判断
- 1.如果观察者所在的宿主不活跃了,不分发
- 2.如果
observer.mLastVersion >= LiveData的mVersion
不分发,最初observer.mLastVersion
初始化值为-1
,然后LiveData
的mVersion
在创建之初也等于-1
,如果LiveData
发送过数据了,这个mVersion
就不等于-1
了,每次setValue(T value)
的时候都会mVersion++
,所以第一次注册数据的时候,
observer.mLastVersion = -1
,mVersion=0
,-1 >= 0
么?显然条件不满足,然后就会执行下面的数据分发,就会出现黏性事件 - 3.分发数据
4.普通消息分发流程
- 即调用
postValue
,setValue
才会触发消息的分发
来直接上源码,先看
postValue(T value)
public abstract class LiveData<T> {
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//直接调用setValue
setValue((T) newValue);
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
//1.先把消息保存成成员变量mPendingData
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//2.用handler把消息发送到主线程中
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
}
该方法可以用在子线程,所以这里会使用handler.post先发送到主线程,在分发消息
- 1.先把消息保存成成员变量
mPendingData
- 2.用
handler
把消息发送到主线程中 - 3.在
Runnable
中,直接调用setValue((T) newValue);
接下来看下setValue(T value)
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
mVersion++
记录当前发送的消息的次数,用于和observer
的version
作对比,防止消息重复,
接下来看dispatchingValue(@Nullable ObserverWrapper initiator)
,流程就和分析黏性事件的后面流程一样了,最后会调用considerNotify(iterator.next().getValue());
经过一系列判断,真正的把事件发送出去
网友评论