我有一个livedata,每次数据库更新时都会发出。当特定屏幕打开时,该实时数据将立即发出,无论数据库中存在什么值。然后,进行网络调用以更新数据库。更新数据库后,实时数据将再次发出。这导致非常连续的两次排放。随后对数据库的更新将正常工作,因为每当更新数据库时,只有一次发射。仅是第一次,非常连续地进行了2次更新。我想避免这种情况。
避免这种情况的想法将是这样的。当实时数据发出时,等待Xs。如果这些X中还有另一个发射,则丢弃旧发射中的数据并使用新发射。再次等待Xs。如果这些X中没有发射,请使用最新数据。
这看起来很像节流,但只有一次。我想知道是否有一种简单的方法来执行诸如使用LiveData或MediatorLiveData的操作。
答案 0 :(得分:0)
您可以在第一个Runnable
事件之后按照需要的超时发布延迟的LiveData
。
每个LiveData
更新都会删除已发布的Runnable
,然后再次发布。
答案 1 :(得分:0)
您可以使用MediatorLiveData和布尔值来实现此目的。
LiveData<Model> mDbLiveData;
MediatorLiveData<Model> mFinalLiveData = new MediatorLiveData();
private boolean mLoadedFromAPI = false;
// Load db data in mDbLiveData
mDbLiveData = // Data from DB
// Add mDbLiveData as source in mFinaliveData
mFinalLiveData.addSource(mDbLiveData, dbData -> {
if (mLoadedFromAPI) mFinalLiveData.postValue(dbData);
});
答案 2 :(得分:0)
我对解决方案做了一些修改以适合我的用例:
fun <T> LiveData<T>.debounceOnce(duration: Long,
coroutineContextProvider: CoroutineContextProvider): LiveData<T> {
return MediatorLiveData<T>().also { mediatorLivedata ->
var shouldDebounce = true
var job: Job? = null
val source = this
mediatorLivedata.addSource(source) {
if (shouldDebounce) {
job?.cancel()
job = CoroutineScope(coroutineContextProvider.IO).launch {
delay(duration)
withContext(coroutineContextProvider.Main) {
mediatorLivedata.value = source.value
shouldDebounce = false
}
}
} else {
job?.cancel()
mediatorLivedata.value = source.value
}
}
}
}
open class CoroutineContextProvider @Inject constructor() {
open val Main: CoroutineContext by lazy { Dispatchers.Main }
open val IO: CoroutineContext by lazy { Dispatchers.Default }
}