一般我们在连续多次调用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 ConstantConditionsmMainHandler.post(runnable);}
那么按这个执行逻辑只有第一次postValue的时候,也就是值为0的时候,会向主线程加入一条执行消息,值为1和2时不会向主线程加入消息,但是此时的mPendingData 的值会变成2,在消息被执行时,代码如下:
private final Runnable mPostValueRunnable = new Runnable() {@SuppressWarnings("unchecked")@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}setValue((T) newValue);}};
会执行第一条消息但是值为最后一个值,这也就是为啥postValue只有最后一次赋值是有效的,postValue最后还是会调用setValue,所以他们的区别就是每次setValue都是有效的而postValue只有最后一次赋值是有效的。
如果面试的时候有人问你,连续发送几条postValue按home键退到桌面再返回会收到几次通知,我想现在你肯定会回答只有最后一次通知会收到。