Хобрук: Ваш путь к мастерству в программировании

Обновление элемента Recyclerview DiffUtil

У меня есть бесконечная прокрутка в моем recyclerview, поэтому она будет обновляться при появлении новых данных. и я использую DiffUtil для обновления данных в recyclerview. DiffUtil обновляет данные, но всякий раз, когда есть данные обновления, recyclerview прокручивается вверх, и это выглядит так: «используя notifydatasetchanged ()». вот мой DiffUtil и мой адаптер для обновления данных.

class ProductDiffUtil(
    val oldProductList: List<ProductModel>, val newProductList: List<ProductModel>
) : DiffUtil.Callback() {

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldProductList[oldItemPosition].id == newProductList[newItemPosition].id
    }

    override fun getOldListSize(): Int = oldProductList.size

    override fun getNewListSize(): Int = newProductList.size

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldProductList[oldItemPosition] == newProductList[newItemPosition]
    }

    override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
        return super.getChangePayload(oldItemPosition, newItemPosition)
    }
}

Вот мой адаптер для обновления данных

fun addProductList(productList: List<ProductModel>?) {
        val diffResult = DiffUtil.calculateDiff(ProductDiffUtil(this.productList, productList!!))
        this.productList.addAll(productList)
        diffResult.dispatchUpdatesTo(this)
    }

Пожалуйста, помогите мне с этим. он отлично работает, когда я использую notifyItemRangeChanged()... так что я должен использовать для обновления данных в recyclerview для лучшей практики.

https://drive.google.com/open?id=1SapXW2wusmTpyGCRA9fa0aSLCYNL1fzN


  • Используйте метод notifyitemrangeinserted. 20.02.2020
  • Сначала я использовал notifyItemRangeInserted(), но diffUtil делает список быстрее, поэтому я пытаюсь его использовать. 20.02.2020
  • Как насчет DiffUtil.ItemCallback<T>() вместо DiffUtil.Callback. 20.02.2020
  • Как вы внедряете адаптер? вы используете библиотеку подкачки или она сделана на заказ? 21.02.2020

Ответы:


1

Вы сравниваете предыдущее содержимое только с новыми элементами, а не со списком со всеми добавленными элементами.

Представьте, что this.productList в настоящее время 1,2,3, а новый productList - 4,5,6. Когда вы бежите

DiffUtil.calculateDiff(ProductDiffUtil(this.productList, productList!!)

Он сравнит 1 с 4, 2 с 5 и т. д. и сделает вывод, что все изменилось и новых элементов не добавилось. (примечание: это упрощение алгоритма DiffUtil, но служит для иллюстрации сути)

Вместо этого, если вы хотите использовать DiffUtil:

val oldList = ArrayList(productList)
this.productList.addAll(productList)
val diffResult = DiffUtil.calculateDiff(ProductDiffUtil(oldList, productList!!)
diffResult.dispatchUpdatesTo(this)

или, поскольку вы точно знаете, сколько элементов добавляется и где, просто используйте notifyItemRangeInserted и избегайте копирования:

val oldSize = this.productList.size
this.productList.addAll(productList)
notifyItemRangeInserted(oldSize, productList.size)
20.02.2020
  • fun addProductList(productList: List‹ProductModel›?) этот метод обновляет только новые данные списка из API. поэтому, если я это сделаю, размер списка не изменится. Например, this.productlist — это 1,2,3, а новый список продуктов — это 4,5,6. он не будет содержать 1,2,3,4,5,6. Я пробовал, как вы сказали, но это не соответствует моей потребности. Как я могу получить это? Можете ли вы показать мне пример или другие? 21.02.2020
  • А, понятно - из вопроса это не ясно. Я обновил свой ответ, чтобы принять это во внимание - посмотрите и посмотрите, решит ли это вашу проблему. Это имеет гораздо больше смысла, учитывая поведение. 21.02.2020
  • Спасибо за ваш ответ. это помогает мне решить мою проблему. извини за поздний повтор братан. 26.02.2020

  • 2

    Проверьте, не был ли уже установлен менеджер компоновки, и получите текущую позицию прокрутки. Как это:

    var itemPostion= 0
    if(myRecyclerView.layoutmanager != null){
      itemPostion = (myRecyclerView.layoutmanager as LinearLayoutManager)
    .findFirstCompletelyVisibleItemPosition()
    }
    

    Вы можете ознакомиться с этим примером проекта на странице GitHub

    20.02.2020
  • В этом нет необходимости, они не должны заменять адаптер. 21.02.2020
  • @RyanMentley это не замена адаптера. Он восстанавливает последнюю предыдущую позицию прокрутки, которую он хотел решить, вместо прокрутки вверх при обновлении данных. 21.02.2020
  • RecyclerView по умолчанию не прокручивается вверх при обновлениях. Это не должно быть необходимо. 21.02.2020
  • Новые материалы

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...