连续调用多次 LiveData 的 postValue 方法,结果只有最后一次响应,前面的消息都被吞了
问题原因:
postValue 方法实现在
androidx.lifecycle.LiveData#postValue
protected void postValue(T value) {
boolean postTask;
synchronized(this.mDataLock) {
postTask = this.mPendingData == NOT_SET;
this.mPendingData = value;//1
}
if (postTask) {
ArchTaskExecutor.getInstance().postToMainThread(this.mPostValueRunnable);//2
}
}
ArchTaskExecutor 本质是一个主线程的 Handler,所以 postValue 方法其实是使用 Handler 的 post 方法来实现在主线程通知 Observer 对象的。
注释 1 处 mPendingData 用于储存即将修改的值。
再看 mPostValueRunnable 的定义
public LiveData() {
this.mPendingData = NOT_SET;
class NamelessClass_1 implements Runnable {
NamelessClass_1() {
}
public void run() {
Object newValue;
synchronized(LiveData.this.mDataLock) {
newValue = LiveData.this.mPendingData;//1
LiveData.this.mPendingData = LiveData.NOT_SET;
}
LiveData.this.setValue(newValue);
}
}
this.mPostValueRunnable = new NamelessClass_1();//2
this.mData = NOT_SET;
this.mVersion = -1;
}
可以看到 mPostValueRunnable 本质是 NamelessClass_1 对象,在其 run 方法中,会读取 mPendingData 的值,然后通过调用 setValue 方法使其通知 Observer 对象。
然而,当短时间内调用多次 postValue 方法时,则容易出现如下时序问题:
综上,此种情况下,Observer 只收到值为 B 的 onChange 回调,值为 A 的onChange 被吞了,所以问题发生了。
该问题可能发生在同线程也可能发生在不同线程之间,根本原因是,postValue 方法和实际执行通知 Observer 的操作之间存在时间差,这个是 Handler 的机制所导致的
方案一:在同一个 LiveData 对象需要频繁调用 postValue 方法时,改用 setValue 方法,避免消息丢失
方案二:优化业务逻辑,将 LiveData 对象的职能分隔开,避免频繁调用 postValue 方法