一般我们在连续多次调用postValue时会出现只有最后一个值通知观察者返回过来,也就是说多次调用postValue时,只有最后一次调用是有效的,而setValue时每一个值的变化都会通知到观察者,也就是说每一次调用都是有效的,那么这是为什么?且看postValue的源码:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
在设置多次值的时候,比如一次设置值为0到2,第一次进这个方法的时候,mPendingData的值为NOT_SET,所以postTask的值true,所以if (!postTask) {
return;
}
不会返回,会继续执行到 ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);这个方法,这个方法其实就是将消息放到UI线程也就是主线程的消息队列里面等待执行,实现代码如下:
public void postToMainThread(@NonNull Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = createAsync(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
那么按这个执行逻辑只有第一次postValue的时候,也就是值为0的时候,会向主线程加入一条执行消息,值为1和2时不会向主线程加入消息,但是此时的mPendingData 的值会变成2,在消息被执行时,代码如下:
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
会执行第一条消息但是值为最后一个值,这也就是为啥postValue只有最后一次赋值是有效的,postValue最后还是会调用setValue,所以他们的区别就是每次setValue都是有效的而postValue只有最后一次赋值是有效的。
如果面试的时候有人问你,连续发送几条postValue按home键退到桌面再返回会收到几次通知,我想现在你肯定会回答只有最后一次通知会收到。