Обновить текущую страницу или обновить данные в библиотеке Paging 3 Android Kotlin
Я новичок в библиотеке Paging 3 в android kotlin. Я хочу безлимитный трафик. Итак, я обнаружил, что библиотека Paging 3 полезна в моем случае. Я использовал PagingSource для создания списка. Я не использую Room. У меня есть вложенный recyclerView. Я использую PagingDataAdapter с diff для моего Recyclerview. Я использовал рекомендованный учебник для библиотеки подкачки из codelab и мне это удалось без проблем. Мне трудно обновить элемент. Я использовал источник подкачки для создания списка, а внутри списка у меня есть некоторые данные, которые поступают с сервера. Я полностью все это без проблем. Но как обновить адаптер или уведомить данные изменились в reyclerview. У меня уже есть механизм для получения обновленного списка. Я искал, как обновить адаптер в каком-то месте, но везде упоминается использование invalidate() из DataSource. DataSource используется в подкачке 2, верно?. Теперь он находится внутри Paging 3 согласно документации в Migrate to Paging 3. Я использовал Flow для получения данных. Этот код находится внутри класса viewmodel.
fun createRepo(data: List<String>, repository: RepositoryData): Flow<PagingData<UnlimitData>> {
return repository.getStreamData(data).cachedIn(viewModelScope)
}
Я передаю список, который исходит из sever. Функция getStreamData возвращает элементы с данными типа int и string. Мои данные класс
data class UnlimitData(val id: Int, val name: String)
createRepo вызывает мой класс активности для отправки данных в adpater.
lifecycleScope.launch {
viewModel.createRepo(serverData,repository).collectLatest { data ->
adapter.submitData(data)
}
}
Это мой код адаптера:-
class unlimitedAdapter() :
PagingDataAdapter<UnlimitData, RecyclerView.ViewHolder>(COMPARATOR) {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = getItem(position)
if (item != null) {
(holder as UnlimitedViewHolder).bind(item)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return UnlimitedViewHolder.create(parent)
}
companion object {
private val COMPARATOR = object : DiffUtil.ItemCallback<UnlimitData>() {
override fun areItemsTheSame(oldItem: UnlimitData, newItem: UnlimitData): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: UnlimitData, newItem: UnlimitData): Boolean = oldItem == newItem
}
}
}
Я добавил логику для вставки / обновления данных в список с помощью RetroFit. Мой список успешно обновлен, но я не могу обновить reyclerview.
Заранее спасибо.
2 ответа
Для того, чтобы пейджинг мог забрать новинки, вам нужно будет позвонить
PagingSource.invalidate()
довести до сведения
Pager
что ему нужно получить новый
PagingSource
и перезагрузите страницы. Вы захотите отслеживать все
PagingSource
s ваша фабрика производит и аннулирует их каждый раз, когда вы обновляете резервный набор данных из сети.
РЕДАКТИРОВАТЬ: что-то вроде этого, но это очень грубый прототип
abstract class InvalidatingPagingSourceFactory<K,V> : () -> PagingSource<K,V> {
private val list = mutableListOf()
abstract fun create()
override final fun invoke() {
create().also { list.add(it) }
}
fun invalidate() {
while (list.isNotEmpty()) { list.removeFirst().invalidate() }
}
}
Когда мы используем метод adapter.refresh(), он обновляет последние данные и привязывается к макету.
Но это не перезагружает представление ресайклера с помощью Position. В этом случае вы получите неправильную позицию.
Потому что в DiffUtils вы правильно сопоставляете. Таким образом, всякий раз, когда вы обновляете, он будет связывать только эти новые, а не связанные данные.
Итак, решение состоит в том, что вы должны сделать ложными DiffUtils. В этом случае PageSource обновит полный список и позицию.
Например: oldItem.id ==-1
private val COMPARATOR = object : DiffUtil.ItemCallback<UnlimitData>() {
override fun areItemsTheSame(oldItem: UnlimitData, newItem: UnlimitData): Boolean =
oldItem.id ==-1
override fun areContentsTheSame(oldItem: UnlimitData, newItem: UnlimitData): Boolean = oldItem == newItem
}