时人不识凌云木,直待凌云始道高
一,基本使用
基本使用请看文章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);}@MainThreadprotected 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();}@Overridepublic void postValue(T value) {super.postValue(value);}@Overridepublic 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")@Overridepublic 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) {// ignorereturn;}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>() {@Overridepublic 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;//观察者的版本@Overridepublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {//每次订阅的时候,先把版本同步observerVersion = mVersion;super.observe(owner, new Observer<T>() {@Overridepublic void onChanged(T t) {if (mVersion != observerVersion) {observer.onChanged(t);}}});}@MainThreadpublic void setValue(T value) {mVersion++;super.setValue(value);}}