如何在 Recyclerview 中正确使用 DiffUtil 更新数组列表?
Posted
技术标签:
【中文标题】如何在 Recyclerview 中正确使用 DiffUtil 更新数组列表?【英文标题】:How to properly use DiffUtils in Recycler view to update array list? 【发布时间】:2021-12-07 04:41:32 【问题描述】:我正在为 recyclerview 实现 diffutils 以通知列表。在搜索过滤器时,recyclerview diffutils 有效。但是当我单击列表项应用程序崩溃时 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 && 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
&& languageNativeName == languageNativeName1
&& languageCode == languageCode1
&& updatedAt == updatedAt1
&& defaultLanguage == defaultLanguage1
@Nullable
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any?
return super.getChangePayload(oldItemPosition, newItemPosition)
我需要使用 diffutils 更新 recyclerview 请提及他们在我的代码中是否有任何更正
提前致谢
【问题讨论】:
【参考方案1】:你可以查看这个 repo Githup ripo
我尝试编辑您的代码
<script src="https://gist.github.com/alihrhera/109ec71245e40c953451a68627a1dc60.js"></script>
run time gif gits the code
【讨论】:
感谢您的评论。我也在做同样的事情。一切正常,但 recyclerview 没有更新,这是我的问题 执行 whta 时不更新?添加或删除或编辑项目? 搜索过滤时 过滤代码在哪里? 我添加我的过滤器查询请检查【参考方案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()
【讨论】:
以上是关于如何在 Recyclerview 中正确使用 DiffUtil 更新数组列表?的主要内容,如果未能解决你的问题,请参考以下文章
一起Talk Android吧(第五百零一回:如何正确地更新RecyclerView中的数据)
如何使用 LiveData 正确更新 Android 的 RecyclerView?