Обновить текущую страницу или обновить данные в библиотеке 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и перезагрузите страницы. Вы захотите отслеживать все PagingSources ваша фабрика производит и аннулирует их каждый раз, когда вы обновляете резервный набор данных из сети.

РЕДАКТИРОВАТЬ: что-то вроде этого, но это очень грубый прототип

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
    }
Другие вопросы по тегам