1

To properly implement a DiffUtil.ItemCallback<T> passed inside the constructor of ListAdapter, both areItemsTheSame and areContentsTheSame must be implemented.

Now for areItemsTheSame it is advised that a unique identifier of type of . So for my case where is a data class without a deducible unique identifier, how am I supposed to implement it properly? When simply doing oldItem == newItem in both functions, I obviously get a flashing animation on the item since it thinks it's a completely different item since areItemsTheSame returned false.

So how do people fix this properly? Would returning true anyway if the data type is the same which would then trigger the areContentsTheSame be a fix? And if not, why? If I do that currently, the recycler properly understands that just some data has changed, and only the necessary parts of the view "flash" with the new data.

Stylianos Gakis
  • 862
  • 8
  • 19
  • How do you know when items are different if you have no unique identifier? Post your data class(es). What's the minimum data change that would make you decide that the objects are the same (or different)? Surely you must have thought of implementing something, you can even _add_ one if you need to. `areItemsTheSame` is intended to quickly find if only the content of a position changed (an optimization) or if the item has now moved in which case a full re-bind of the viewHolder is needed. So you need to have a way to uniquely identify a row, whether this is 1 field or "n" is up 2 you. – Martin Marconcini Sep 27 '21 at 09:32

1 Answers1

1

So how do people fix this properly?

The "solution" is to have a unique identifier for each row (which is good advice for most relational data structures).

You can combine fields in either method, the callback offers you both items (old and new) and you get to decide what to do/compare in there.

When the items "are the same" (as determined by your implementation), then this allows the RecyclerView/Adapter combo to make assumptions (and optimizations).

When the items are determined to have changed (meaning they are now two different items), then a different set of things must happen (animations, rebinding, determining the viewType, etc.). More work for the UI.

So don't fight the framework, instead provide a unique identifier, even if it's composed of more than one field. I'm curious to see your data class to understand how comes there's no unique way to identify a single row.

Martin Marconcini
  • 26,875
  • 19
  • 106
  • 144
  • The model comes from [here](https://github.com/HedvigInsurance/android/blob/6b65a2f1b34e187af0b376bc514e0286766c69d3/app/src/main/java/com/hedvig/app/feature/offer/ui/OfferModel.kt#L17) which is constructed [here](https://github.com/HedvigInsurance/android/blob/6b65a2f1b34e187af0b376bc514e0286766c69d3/app/src/main/java/com/hedvig/app/feature/offer/OfferItemsBuilder.kt#L24) from a generated model from GraphQL. There is no explicit uniqueness there. But since it's part of a ConcatAdapter, it's always one Header type. So maybe I can make it always true, to let it know it doesn't have to flash – Stylianos Gakis Sep 27 '21 at 10:03
  • So you're saying that two different `OfferModel` can have the same `title` and `startDate` for example? Can't you ask the backend to provide a unique identifier (I'm sure they have one, GraphQL or not, this ends up being in a table somewhere). *especially* being GraphQL where you can shape the query at your discretion. – Martin Marconcini Sep 27 '21 at 10:39
  • "So maybe I can make it always true, to let it know it doesn't have to flash" This will work, but you're _fooling_ the system and perhaps playing with fire. HOwever, if you don't see any major problem with this in the future then by all means. – Martin Marconcini Sep 27 '21 at 10:44
  • 1
    Yes Martin, this is probably the best approach. Very good to learn this in general, don't play with the system, try to just go with the rules. In this case I said that as an option because as far as I know, only 1 of those are shown in that adapter. But as I said, "as far as I know". If I am mistaken this *can* lead into problems in the future. But thank you so much for your input, it has been very helpful! – Stylianos Gakis Sep 27 '21 at 11:26