I was following along the Android Room With a View tutorial.
The tutorial makes use of DiffUtil to compute changes in the list and update the RecyclerView accordingly.
However, when removing or adding items to the RecyclerView, DiffUtil always causes the entire RecyclerView to reload, instead of calling the correct notifyItemRemoved or notifyItemInserted.
My Adapter:
class MarksAdapter(private val context: Context) :
ListAdapter<Mark, MarksAdapter.MarkViewHolder>(MarksComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MarkViewHolder {
return MarkViewHolder.create(parent)
}
override fun onBindViewHolder(holder: MarkViewHolder, position: Int) {
val mark = getItem(position)
holder.bind(context, mark)
}
class MarkViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private var mark: Mark? = null
fun bind(context: Context, mark: Mark) {
this.mark = mark
// Removed for brevity...
}
companion object {
fun create(parent: ViewGroup): MarkViewHolder {
val view: View =
LayoutInflater.from(parent.context).inflate(R.layout.card_view, parent, false)
return MarkViewHolder(view)
}
}
}
class MarksComparator : DiffUtil.ItemCallback<Mark>() {
override fun areItemsTheSame(oldItem: Mark, newItem: Mark): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: Mark, newItem: Mark): Boolean {
return oldItem == newItem
}
}
}
From the activity/fragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerViewMarks.apply {
marksAdapter = MarksAdapter(context)
adapter = marksAdapter
layoutManager = LinearLayoutManager(this@MarksOverviewFragment.requireContext())
}
marksViewModel.allMarks.observe(viewLifecycleOwner) { marks ->
marks?.let { marksAdapter.submitList(it) }
}
}