和上一篇Lifecycle组件一样,LiveData也是一个观察者机制的东西,订阅者订阅LiveData后,LiveData数据发生变化,就会通知到订阅者;
伪代码如下:
6. val myLiveData = MutableLiveData<String>()
7. myLiveData.observe(LifecycleOwner, Observer {
void onChanged(String t){
Log.i("tag", t)
}
})
8. myLiveData.postValue("new value")
9. 打印执行new value
上面代码就是LiveData的一个简单使用,那么它背后的原理如何,请看下分析
MutableLiveData类是LiveData类的子类,基本和LiveData一样,没有做特别的改变;当然除了MutableLiveData子类外,还有RoomTrackingLiveData类,也是LiveData的另一个实现,RoomTrackingLiveData主要是用于Database相关的操作,这里我们只分析MutableLiveData,其代码如下:
public class MutableLiveData<T> extends LiveData<T> {
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);
}
}
liveData添加订阅者,主要是通过observer方法添加进去,需要注意的是第一个参数必须是LifecycleOwner类型,表示订阅者自己本身也必须有一个状态,在订阅者死亡后LiveData就不在继续给你同步消息了,添加observer的逻辑如下图:
首先,在Activity里面添加订阅者到liveData,因为Activity本身就实现了LifecycleOwner接口,所以第一个参数为this即可,第二个就是Observer对象;然后就进入到LiveData类的observer里面去,如下代码:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
如果添加进入的owner已经都是DESTROYED状态,那么久没必要在添加进来了
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
内部封装类,将owner和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;
}
owner.getLifecycle().addObserver(wrapper);
}
LifecycleBoundObserver实现了LifecycleEventObserver,方便订阅者将自己的状态同步过来
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
订阅者那边如果生命状态发生变化会把状态通知过来
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
如果订阅者转头为DESTROYED,那就把这个订阅者从livedata中删除掉
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
状态通知下去,
activeStateChanged(shouldBeActive());
}
这块代码主要作用是订阅者的状态由false变为true的时候,要给他来一次事件发布
void activeStateChanged(boolean newActive) {
如果状态都一样,那么没必要把数据在发布给订阅者
if (newActive == mActive) {
return;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
/*省略部分代码*/
如果存活就把value发送给订阅者
if (mActive) {
dispatchingValue(this);
}
}
}
mObservers.putIfAbsent 将订阅者添加到mObservers里面,mObservers是SafeIterableMap类型,就是一个双链表数据结构,存储元素类型为Entry:
public V putIfAbsent(@NonNull K key, @NonNull V v) {
Entry<K, V> entry = get(key);
if (entry != null) {
return entry.mValue;
}
put(key, v);
return null;
}
protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
Entry<K, V> newEntry = new Entry<>(key, v);
mSize++;
if (mEnd == null) {
mStart = newEntry;
mEnd = mStart;
return newEntry;
}
mEnd.mNext = newEntry;
newEntry.mPrevious = mEnd;
mEnd = newEntry;
return newEntry;
}
代码很简单,直接看就行;
最后在observer方法最后一句owner.getLifecycle().addObserver(wrapper),也就是会把这个wrapper添加到订阅者(Activity)那边去,为什么这么做呢?主要是添加过去后,方便Activity生命周期变化,进行状态同步过来
在MutableLiveData中有set和post两种方法更新,post可以在非主线程使用,而set必须在子线程使用,我们用post来看看:
protected void postValue(T value) {
boolean postTask;
多线程处理mPendingData,所以必须加锁
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
postTask为false,说明mPendingData已经有值,并且正在把值分发给订阅者;
所以这里不需要再次分发,直接返回,只修改mPendingData即可
if (!postTask) {
return;
}
开始在主线程执行mPostValueRunnable
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
上述代码主要是先获取同步锁,检查mPendingData是否已经设置,更新mPendingData,如果已经改变,说明消息发布任务已启动,无须再次启动,然后进入postToMainThread方法看看:
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
获取主线程的Looper,创建一个异步的Handler
mMainHandler = createAsync(Looper.getMainLooper());
}
}
}
handler发送runnable任务
mMainHandler.post(runnable);
}
这里线程切换就是handler来实现的,需要了解Android handle机制看这里
最后,再回头看看这个Runnable是什么任务?
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
写入值和发送值不能同时处理,所以必须要用同一把锁锁住
synchronized (mDataLock) {
把值拷贝到新的newValue去,同时要设置mPendingData为NOT_SET,
方便下次值的写入
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
没写入一次值,要为其赋一个版本号
mVersion++;
mData = value;
dispatchingValue(null);
}
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;
}
private void considerNotify(ObserverWrapper observer) {
如果这个订阅者mActive为false,也就是小于STARTED状态,就没必要消息分发了
if (!observer.mActive) {
return;
}
这里检查的不是订阅者,是订阅者那边的LifecycleOwner的状态,这个状态比上面的可靠
并把状态同步给订阅者,此时订阅者状态是正确的,而且也没必要去消息分发;
这里为什么要这么做?是因为订阅者observer可能还不是最新的状态,所以需要把LifecycleOwner
同步给订阅者,以免做无用的消息分发
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
这里搞不懂,mLastVersion都是为啥要这么多,会出现大于的情况吗,我觉得不会出现,
因为 mLastVersion都是mVersion赋值给他的,他肯定比mVersion小啊
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
执行onChanged方法,就是最初的Observer的回调函数
observer.mObserver.onChanged((T) mData);
}
以上消息分发就完成了,做个小结:
订阅者自身状态DESTROYED死亡后,需要将自己从LiveData中remove掉,主要发生在LiveData的内部类LifecycleBoundObserver中的onStateChanged方法里面,因为LifecycleBoundObserver实现了LifecycleEventObserver接口,在订阅者那边LifecycleOwner提前在LiveData的observer方法最后将LifecycleBoundObserver添加进去了,也就是添加到了LifecycleOwner的订阅者集合,所以当LifecycleOwner状态变化时,会将状态同步给他的订阅者,也就是LifecycleBoundObserver,当处于DESTROY时,就会将同步调用LifecycleBoundObserver的onStateChanged方法,方法如下:
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@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);
}
上面的文字描述比较复杂,难理解,你要理解的是LifecycleBoundObserver是对LiveData的订阅封装类,LiveData添加了LifecycleBoundObserver,用于消息通知;而LifecycleOwner也添加了这个LifecycleBoundObserver,这边添加是为了生命状态同步,需要配合Android Lifecycle疑问看看;大致简图如下:
LiveData采用观察者模式,一有数据更新时,会发布给订阅者;与很好的与视图解耦,也无须担心内存泄漏的问题,除非LiveData本身持有其他的外部引用导致自身无法释放;因为在Activity这端,会实时的把自身状态同步给LifecycleBoundObserver,以便在DESTROY状态下,liveData会自动remove掉订阅者