前言
最近的项目重构中加入LiveData框架,并且小码的T-MVVM也是用了LiveData框架,好不好用你试试就知道(小码口头禅),对于LiveData使用的时候并未做太多的理解,于是乎翻了翻LiveData源代码,在此做下笔记。
什么是LiveData
LiveData是一个数据持有类。它具有以下特点:
LiveData能为我们做什么
从使用分析
privateMutableLiveData<String> mData= newMutableLiveData();
mBookData.postValue( "Hello LiveData");
// mBookData.setValue("Hello LiveData");
此处postValue和setValue的区别,下文会提
注册观察者并监听数据变化:
mData.observe( this, newObserver< String>() {
@Override
public voidonChanged( @NullableStringstr) {
Toast.makeText( this, str, Toast.LENGTH_SHORT).show();
}
});
使用非常简单,仅此而已
通过observe方法注册观察者,哪咋们就看看observe里面具体干了什么,源代码165行走起,
//注册观察
@MainThread
publicvoidobserve(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer){
if(owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = newLifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if(existing != null&& !existing.isAttachedTo(owner)) {
thrownewIllegalArgumentException( "Cannot add the same observer"
+ " with different lifecycles");
}
if(existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
observe方法接收2个参数,一个是具有生命周期的LifecycleOwner,另一个是观察者Observer ,首先判断LifecycleOwner当前的生命周期是否为Destroyed,如果是则直接 return;如果不等于Destroyed,接下来往下看, 此处new了一个内部类LifecycleBoundObserver对象并且构造方法传入了具有生命周期的LifecycleOwner和观察者,这是个什么鬼,看看他的具体方法,LifecycleBoundObserver继承自ObserverWrapper,并实现GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver类就是把Observer和生命周期关联起来,ok,那我们先看看LifecycleBoundObserver方法,源代码349行走起,
classLifecycleBoundObserverextendsObserverWrapperimplementsGenericLifecycleObserver{
@NonNullfinalLifecycleOwner mOwner;
LifecycleBoundObserver( @NonNullLifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
booleanshouldBeActive(){
returnmOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
publicvoidonStateChanged(LifecycleOwner source, Lifecycle.Event event){
if(mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
booleanisAttachedTo(LifecycleOwner owner){
returnmOwner == owner;
}
@Override
voiddetachObserver(){
mOwner.getLifecycle().removeObserver( this);
}
}
此方法中,我们先看onStateChanged()方法,当生命周期变化时会回调,如果getCurrentState() == DESTROYED则removeObserver,反之则调用父类ObserverWrapper的activeStateChanged()方法,源代码382行走起,
privateabstractclassObserverWrapper{
finalObserver<T> mObserver;
booleanmActive;
intmLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}
abstractbooleanshouldBeActive();
booleanisAttachedTo(LifecycleOwner owner){
returnfalse;
}
voiddetachObserver(){
}
voidactiveStateChanged(booleannewActive){
if(newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
booleanwasInactive = 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);
}
}
}
activeStateChanged()是干嘛的,首先判断activeState新旧状态是否相同,不同则把新的状态赋给mActive,是生命周期状态处于ACTIVE情况下的逻辑处理。如果新的状态和旧的状态相同则直接返回。这里有个常量LiveData.this.mActiveCount,看注释可以理解为观察者处于活动状态
个数,往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive为true,即观察者处于活动状态
个数从0变为1个则调用onActive(); 观察者处于活动状态
个数从1变为0时则调用onInactive()。然而onActive(),onInactive()并没有任何实现代码。好了,接下来继续往下看dispatchingValue(this);应该就是数据变化消息调度。源代码112行走起,
private voiddispatchingValue( @NullableObserverWrapper initiator) {
if(mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do{
mDispatchInvalidated = false;
if(initiator != null) {
considerNotify(initiator);
initiator = null;
} else{
for( Iterator< Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if(mDispatchInvalidated) {
break;
}
}
}
} while(mDispatchInvalidated);
mDispatchingValue = false;
}
前面的几行if 判断姑且先不看,先看从if(initiator != null)开始看,如果initiator!= null调用considerNotify(initiator)方法;源代码91行走起,
privatevoid 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;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
看见没有最后一行代码 observer.mObserver.onChanged((T) mData); Observer的数据变化回调;好了我们再回过头看看initiator == null的逻辑,
for( Iterator< Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if(mDispatchInvalidated) {
break;
}
}
如果initiator == null 则会通过迭代器mObservers遍历获取ObserverWrapper,最终还是调用considerNotify方法;既然有取ObserverWrapper,咋们再看看在哪儿存的,在源码171行:
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if(existing != null&& !existing.isAttachedTo(owner)) {
thrownewIllegalArgumentException( "Cannot add the same observer"
+ " with different lifecycles");
}
if(existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
mObservers.putIfAbsent(observer, wrapper)存入容器中,mObservers.putIfAbsent这个添加数据的方式貌似很少见,于是乎在看看mObservers是个什么数据容器,成员变量中:
privateSafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
newSafeIterableMap<>();
这是个什么鬼,貌似以前很少见,查阅资料发现:
SafeIterableMap有以下特性:
1.支持键值对存储,用链表实现,模拟成Map的接口
2.支持在遍历的过程中删除任意元素,不会触发ConcurrentModifiedException
3.非线程安全
感兴趣的可自行查阅,此处不再详细介绍,
最后addObserver添加注册。
下面在看看数据发起通知的逻辑,数据发起通知有2中方式:
publicclassMutableLiveData<T> extendsLiveData<T> {
@Override
publicvoidpostValue(T value){
super.postValue(value);
}
@Override
publicvoidsetValue(T value){
super.setValue(value);
}
}
setValue和postValue2中方式,我们先看看setValue代码:
@ MainThread
protectedvoidsetValue(T value) {
assertMainThread( "setValue");
mVersion++;
mData = value;
dispatchingValue( null);
}
privatestaticvoidassertMainThread(String methodName) {
if(!ArchTaskExecutor.getInstance().isMainThread()) {
thrownewIllegalStateException( "Cannot invoke "+ methodName + " on a background"
+ " thread");
}
}
setValue第一行代码 assertMainThread("setValue");则是判断是否在主线程,所以貌似setValue方式必须在主线程中执行,如果非主线程则抛出异常。
再看看postValue:
protectedvoidpostValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if(!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
则postValue调用postToMainThread方法,最终还是用过setValue方式:
privatefinalRunnable mPostValueRunnable = newRunnable() {
@Override
publicvoidrun(){
Object newValue;
synchronized(mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
因此最终明白为什么setValue方法只能在主线程中调用,postValue可以在任何线程中调用,如果是在后台子线程中更新LiveData的值,必须调用postValue。
至此大概明白了LiveData是干嘛的 ,怎么干的,总的来说还是很好用的,于是乎就有个小小的想法,平时用Eventbus,RxBus什么的,貌似感觉LiveData也可以实现事件总线,既然有了想法,那就干呗,
/**
* 事件总线
*
* @author:tqzhang on 18/9/11 17:22
*/
publicclassLiveBus{
privatestaticvolatileLiveBus instance;
privatefinal Map<Object, MutableLiveData<Object>> mLiveBus;
privateLiveBus() {
mLiveBus = newHashMap<>();
}
publicstaticLiveBus getDefault() {
if(instance == null) {
synchronized (LiveBus.class) {
if(instance == null) {
instance = newLiveBus();
}
}
}
returninstance;
}
/**
*
* subscriber 注册时间 key
*/
public<T> MutableLiveData<T> subscribe(Object subscriber, Class<T> tMutableLiveData) {
checkNotNull(subscriber);
checkNotNull(tMutableLiveData);
if(!mLiveBus.containsKey(subscriber)) {
mLiveBus.put(subscriber, newMutableLiveData<>());
}
return(MutableLiveData<T>) mLiveBus. get(subscriber);
}
}
简单的50行代码实现类似Eventbus,RxBus的功能,小码亲测了,挺好使的。
//发起通知
LiveBus.getDefault().subscribe( "livedata", String. class).postValue( "hello LiveData");
//注册观察
LiveBus.getDefault().subscribe( "livedata", String. class).observe( this, newObserver< String>() {
@Override
public voidonChanged( @NullableStrings) {
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
});