簡體   English   中英

使用初始超時觀察 livedata

[英]Observe livedata with an initial timeout

我有一個 livedata,每次數據庫中有更新時都會發出。 當特定屏幕打開時,此 livedata 會立即發出數據庫中的任何值。 然后,進行網絡調用以更新數據庫。 更新數據庫后,livedata 再次發出。 這導致非常快速的連續兩次排放。 對數據庫的后續更新工作正常,因為每當更新數據庫時只有一次發射。 只有第一次,很快就連續更新了 2 次。 我想避免這種情況。

避免這種情況的想法是這樣的。 當 livedata 發出時,等待 Xs。 如果這些 X 中有另一個發射,則丟棄舊發射中的數據並使用新發射。 再次等待Xs。 如果這些 X 中沒有排放,請使用最新數據。

這看起來與節流非常相似,但只有一次。 我想知道是否有一種簡單的方法可以使用 LiveData 或 MediatorLiveData。

您可以在第一個LiveData事件之后發布延遲的Runnable ,並帶有您想要的超時時間。 每個LiveData更新都會刪除已發布的Runnable並再次發布。

您可以使用 MediatorLiveData 和 boolean val 來實現此目的。

  1. 當加載來自 API 的數據時,創建 mDbLiveData、中介 livedata mFinalLiveData 和 boolean mLoadedFromAPI。
  2. 在 API 成功或失敗時,將 mLoadedFromAPI 設置為 true;
  3. 在 Activity/Fragment 中觀察 mFinalLiveData
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);
});

這篇文章有幫助。 https://medium.com/@guilherme.devel/throttle-operator-with-livedata-and-kotlin-coroutines-ec42f8cbc0b0

我稍微修改了解決方案以適合我的用例:

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 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM