Наблюдать за живыми данными с начальным таймаутом - PullRequest
0 голосов
/ 18 июня 2020

У меня liveata, который выдает каждый раз при обновлении базы данных. Когда открывается конкретный экран, эти живые данные немедленно излучаются с любым значением, которое есть в базе данных. Затем выполняется сетевой вызов для обновления базы данных. После обновления базы данных liveata излучает снова. Это приводит к двум выбросам в очень быстрой последовательности. Последующие обновления базы данных работают правильно cz при каждом обновлении базы данных происходит только одно излучение. Только в первый раз, есть 2 обновления в очень быстрой последовательности. Я хочу избежать этого.

Идея, чтобы избежать этого, была бы примерно такой. Когда излучает ливинг, ждите Xs. Если в этих крестиках есть еще одна эмиссия, отбросьте данные из старой эмиссии и используйте новую. Ждите снова Хк. Если в этих крестиках нет излучения, используйте последние данные.

Это очень похоже на дросселирование, но только один раз. Мне было интересно, есть ли простой способ сделать что-то вроде LiveData или MediatorLiveData.

Ответы [ 3 ]

0 голосов
/ 18 июня 2020

Вы можете использовать MediatorLiveData и логическое значение для достижения этого.

  1. Создайте mDbLiveData, медиатор liveata mFinalLiveData и логическое значение mLoadedFromAPI при загрузке данных из API.
  2. При успешной загрузке API или сбой, установите для mLoadedFromAPI значение true;
  3. Наблюдайте за 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);
});

0 голосов
/ 19 июня 2020

Помог этот пост. https://medium.com/@guilherme.devel / throttle-operator-with-liveata-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 }
}
0 голосов
/ 18 июня 2020

Вы можете отправить сообщение с задержкой Runnable с желаемым таймаутом после первого LiveData события. Каждое LiveData обновление удаляет опубликованное Runnable и публикует его снова.

...