Challenge 3: A DiffUtil.Callback — Solution class ProductDiffCallback( private val oldList: List, private val newList: List ) : DiffUtil.Callback() { override fun getOldListSize() = oldList.size override fun getNewListSize() = newList.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition].name == newList[newItemPosition].name } override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return oldList[oldItemPosition] == newList[newItemPosition] } } // If two lists differ by one product's price changing (same name, e.g. // "Keyboard" going from 49.99 to 39.99 in a sale): // - areItemsTheSame returns TRUE for that product (same name = same // identity), so DiffUtil treats it as the SAME item, not a // remove-then-add. // - areContentsTheSame returns FALSE for that product (data class // equals() compares both name AND price, and price differs), so // DiffUtil marks it as CHANGED. // - The net effect: RecyclerView plays a "changed" animation (a subtle // flash/update) on just that one row, re-running onBindViewHolder // for it specifically — every other row is left completely // untouched, with no animation and no rebinding at all. Notes: - Using product name as the identity key in areItemsTheSame is a simplification for this challenge — in a real app, a genuinely stable unique ID (like a database primary key) is the correct choice, since two different products could coincidentally share a name. - The distinction between areItemsTheSame (identity) and areContentsTheSame (value equality, via the Product data class's auto-generated equals() from Kotlin Fundamentals Chapter 4) is what lets DiffUtil tell "this is a different item entirely" apart from "this is the same item, but something about it changed."