Как правильно использовать DiffUtils в представлении Recycler для обновления списка массивов?

android #kotlin #arraylist #android-recyclerview #android-diffutils

#Android #kotlin #arraylist #android-recyclerview #android-diffutils

Вопрос:

Я внедряю diffutils для recyclerview для уведомления списка. Во время фильтрации поиска diffutils recyclerview работает. Но когда я нажимаю на элемент списка, приложение вылетает с java.lang.Исключение IndexOutOfBoundsException: Index: 1, Size: 1 в то же время, когда я использую приложение notifyDataSetChanged(), сбой не произошел.

Класс модели

 data class LanguageModel (
    @SerializedName("languageName")
    var languageName : String = "",
    @SerializedName("languageNativeName")
    var languageNativeName : String = "",
    @SerializedName("languageCode")
    var languageCode : String = "",
    @SerializedName("updatedAt")
    var updatedAt : String = "",
    @SerializedName("defaultLanguage")
    var defaultLanguage : Boolean = false
)
 

Класс адаптера

 class LanguageSelectionAdapter(var languageModelList : ArrayList<LanguageModel>, var itemClick : LanguageClick)
    : RecyclerView.Adapter<LanguageSelectionAdapter.LanguageSelectionVH>() {

    inner class LanguageSelectionVH(val binding: LanguageListSingleItemBinding)
        : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LanguageSelectionVH {
        val binding = LanguageListSingleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return LanguageSelectionVH(binding)
    }

    override fun onBindViewHolder(holder: LanguageSelectionVH, position: Int) {
        val model = languageModelList[position]
        holder.binding.languageCard.apply {
            if (position == 0 amp;amp; position % 2 == 0) {
                setCardBackgroundColor(ContextCompat.getColor(context, R.color.main_blue))
            } else {
                setCardBackgroundColor(ContextCompat.getColor(context, R.color.main_green))
            }
        }
        holder.binding.nativeLanguageText.text = model.languageNativeName
        holder.binding.originalLanguageText.text = model.languageName
        holder.itemView.setOnClickListener {
            itemClick.langClick(position)
        }
    }

    override fun getItemCount(): Int {
        return languageModelList.size
    }

    fun setData(newLanguageModelList : ArrayList<LanguageModel>) {
        val diffCallback = LanguageSelectionDiffUtils(languageModelList, newLanguageModelList)
        val diffResult = DiffUtil.calculateDiff(diffCallback)
        languageModelList.clear()
        languageModelList.addAll(newLanguageModelList)
        diffResult.dispatchUpdatesTo(this)
    }

}
 

Класс Diffutil

 class LanguageSelectionDiffUtils(
    private val oldList : ArrayList<LanguageModel>,
    private val newList : ArrayList<LanguageModel>
) : DiffUtil.Callback(){

    override fun getOldListSize(): Int {
        return oldList.size
    }

    override fun getNewListSize(): Int {
        return newList.size
    }

    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldList[oldItemPosition].updatedAt == newList[newItemPosition].updatedAt
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        val (languageName, languageNativeName, languageCode, updatedAt,defaultLanguage) = oldList[oldItemPosition]
        val (languageName1, languageNativeName1, languageCode1, updatedAt1,defaultLanguage1) = newList[newItemPosition]
        return languageName == languageName1
                        amp;amp; languageNativeName == languageNativeName1
                        amp;amp; languageCode == languageCode1
                        amp;amp; updatedAt == updatedAt1
                        amp;amp; defaultLanguage == defaultLanguage1
    }


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

}
 

Мне нужно обновить recyclerview с помощью diffutils
пожалуйста, укажите, есть ли какие-либо исправления в моем коде

Заранее спасибо

Ответ №1:

вы можете проверить это репозиторий Githup ripo

я пытаюсь отредактировать ваш код

 <script src="https://gist.github.com/alihrhera/109ec71245e40c953451a68627a1dc60.js"></script> 

время выполнения gif
gits код

Комментарии:

1. Спасибо за комментарий. Я делаю то же самое. Все работает нормально, но recyclerview не обновляется, это была моя проблема

2. нет обновления при выполнении whta? добавить, удалить или отредактировать элемент?

3. во время фильтрации поиска

4. где код фильтра?

5. Я добавляю свой запрос фильтра, пожалуйста, проверьте

Ответ №2:

Запрос фильтра

 private fun perFormFilter(filterText : String) {
        languageList = ArrayList()
        if (filterText.isEmpty() || filterText == null) {
            languageList = languageMainList
        } else {
            for (i in 0 until languageMainList.size) {
                if (languageMainList[i].languageName.lowercase(Locale.ROOT).contains(filterText.lowercase(Locale.ROOT)) ||
                    languageMainList[i].languageNativeName.lowercase(Locale.ROOT).contains(filterText.lowercase(Locale.ROOT)) ||
                    languageMainList[i].languageCode.lowercase(Locale.ROOT).contains(filterText.lowercase(Locale.ROOT))
                ) {
                    languageList.add(languageMainList[i])
                }
            }
        }
        languageSelectionAdapter.setData(languageList)
        //languageSelectionAdapter.notifyDataSetChanged()
    }