Android--Jetpack--LiveData源码分析
时人不识凌云木,直待凌云始道高
一,基本使用
基本使用请看文章Android--Jetpack--LiveData-CSDN博客
二,MutableLiveData
首先说一下我们为什么要用MutableLiveData呢,来看看LiveData的源码:
public abstract class LiveData<T> {
。。。。
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
}
setValue 和postValue 都是protected方法,外面拿不到
同时,这里的setValue使用了注解@MainThread 说明只能在主线程发送数据
再来看看MutableLiveData的源码:
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);
}
}
这是它的全部代码,只是把postValue和setValue这两个方法公开了。其余的都是继承LiveData。
这就是我们为什么使用MutableLiveData的原因。
三,消息发送源码分析
setValue和postValue都是发送数据的,但是setValue只能在主线程发送数据,而postValue却不受线程限制。
我们来看看postValue的源码:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
通过ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);切换到了主线程,再来看看mPostValueRunnable:
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
最终还是调用了setValue,所以说postValue只是多了一个线程切换的操作。
所以我们重点看下setValue的源码:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
首先看看assertMainThread("setValue"):
static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
这个方法的作用就是检查是不是在主线程,不在主线程就抛异常。
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;
}
上面都是判断,主要来看这行代码:
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
这里有个mObservers,我们来看看这是什么:
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
这是一个key为Obsercer,value为ObserverWrapper的map集合。
我们再来看看mObservers是在什么时候添加元素的:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
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);
}
是在observe方法中添加的,先看看observe什么时候调用:
Observer observer =new Observer<String>() {
@Override
public void onChanged(String o) {
System.out.println("yz---"+o);
txt.setText(o);
}
};
//获取viewmodule
model =new ViewModelProvider(this).get(MyViewModel.class);
model.getCount().observe(this,observer);
在上篇使用的时候,我们会在Activity中这样调用observe,第一个参数是Activity,第二个参数是自己定义的观察者。
然后我们再回到observe方法中,首先检查了是不是在主线程,然后判断如果当前Activity的状态是不可用状态,就返回。如果是可用状态,就将Activity和观察者包装成wrapper,并且以观察者为key,wrapper为value添加进mObservers集合。如果这个集合里面不是空的并且不是重复的observer 就执行owner.getLifecycle().addObserver(wrapper);我们在Android--Jetpack--Lifecycle详解-CSDN博客Android--Jetpack--Lifecycle详解-CSDN博客Android--Jetpack--Lifecycle详解-CSDN博客中讲过,这个就会添加进观察者集合中。
了解了mObservers之后,我们再回到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;
}
这里会执行considerNotify(iterator.next().getValue());继续看它的源码:
private void 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;
observer.mObserver.onChanged((T) mData);
}
将上面我们包装的ObserverWrapper传了进来。
首先判断这个观察者是不激活状态,就返回不执行
然后就到了这句代码:
if (observer.mLastVersion >= mVersion) {
return;
}
mVersion刚才出现过,我们看看mVersion:
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
在我们创建new MutableLiveData<>()的时候,会给mVersion赋值START_VERSION=-1
然后我们setValue的时候mVersion会+1.
之后就会走到considerNotify(iterator.next().getValue())方法中。
observer.mLastVersion的初始值:
static final int START_VERSION = -1;
int mLastVersion = START_VERSION;
所以,我们setValue的时候,会走到dispatchingValue方法中,然后会走到considerNotify中,接下来就到了?observer.mObserver.onChanged((T) mData)方法,这时就会回调observer的api把消息发送出来了。
四,数据倒灌和粘性问题
正常我们的执行顺序是:new LiveData-->绑定observer-->setValue执行onChanged
但是当我们跨Activity的时候,可能执行顺序是这样的:
new LiveData-->setValue执行onChanged-->绑定observer
这样会有什么问题呢?
首先,正常的执行流程上面我们已经分析过了。
下面 我们来看看不正常的流程:
new LiveData的时候:
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
mVersion=-1
然后执行setValue:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
mVersion =0
这时不会走到:
private void 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;
observer.mObserver.onChanged((T) mData);
}
因为还没绑定observer:
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;
}
所以此时observer.mLastVersion =-1
但是因为是一个while循环,所以当绑定observer时,然后会走到:
private void 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;
observer.mObserver.onChanged((T) mData);
}
然后我们就会收到消息。
所以就造成了我们订阅之前的消息也收到了。
五,解决方案
public class MyLiveData<T> extends MutableLiveData<T> {
private int mVersion = 0;//被观察者的版本
private int observerVersion = 0;//观察者的版本
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//每次订阅的时候,先把版本同步
observerVersion = mVersion;
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(T t) {
if (mVersion != observerVersion) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(T value) {
mVersion++;
super.setValue(value);
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!