#android #listener #android-livedata
#Android #прослушиватель #android-livedata
Вопрос:
У меня есть a ViewModel
, в котором есть список элементов, которые RecyclerView.Adapter
использует a .
Когда пользователь нажимает на один из этих элементов, может произойти одно или несколько из следующих событий:
- элемент может быть изменен;
- другие элементы могут быть удалены.
Я использовал LiveData
как способ сигнализировать о том, что элемент списка был изменен (более производительный, чем сообщение о том, что весь список был изменен). Но я забывал, что LiveData
может пропускать значения.
Пример:
// on background thread
mutableModificationEvent.postValue(ModificationEvent(...)) // will be skipped
mutableModificationEvent.postValue(ModificationEvent(...))
Какой наиболее подходящий способ выполнить эту работу?
Я знаю, что LiveData#setValue() существует. Но поскольку #postValue
в какой-то момент значения могут быть пропущены и ошибочно добавлены в код, я отбрасываю LiveData
их как вариант.
Комментарии:
1. Я сталкивался с пропуском значений LiveData, но только при получении слишком большого количества обновлений за очень короткий промежуток времени (миллисекунды). Я бы подумал, что это не будет проблемой, если единственные обновления, которые он получает, будут в результате взаимодействия с пользователем?
2. Как насчет того, чтобы объединить их и опубликовать
List<ModificationEvent>
? Конечно, для этого потребуется какая-то синхронизация, очистка предыдущего списка, добавление новых элементов в список и в какой-то момент обновление пользовательского интерфейса.
Ответ №1:
Вероятно, вы могли бы использовать один из реактивных потоков, например, в сопрограммах RxJava или Kotlin. Вот пример потока kotlin (взят отсюда):
val latestNews: Flow<List<ArticleHeadline>> = flow {
while(true) {
val latestNews = newsApi.fetchLatestNews()
emit(latestNews) // Emits the result of the request to the flow
delay(refreshIntervalMs) // Suspends the coroutine for some time
}
}
Вот пример использования потока с преобразованием его в LiveData (ссылка):
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
Я не пробовал это, но похоже, что приведенный выше поток должен выдавать элементы один за другим, и никакие элементы не должны быть пропущены.