Android - what is the meaning of StableIDs?
Asked Answered
U

2

51

I'm implementing a ListAdapter of ExpandableListView, while working i see that i need to overide the function boolean hasStableIds(). Can anyone explain please what is the meaning of stable ids? when I need this?

Unprintable answered 13/8, 2013 at 19:21 Comment(0)
J
67

Stable IDs allow the ListView to optimize for the case when items remain the same between notifyDataSetChanged calls. The IDs it refers to are the ones returned from getItemId.

Without it, the ListView has to recreate all Views since it can't know if the item IDs are the same between data changes (e.g. if the ID is just the index in the data, it has to recreate everything). With it, it can refrain from recreating Views that kept their item IDs.

Jessi answered 13/8, 2013 at 19:29 Comment(4)
e.g. if the ID is just the index in the data, it has to recreate everything Shouldn't this be the opposite of the truth? I mean, if the id is just the index than it's always stable since it will never change. The element at index n will always return an id of n and so will never be changed. And my logic is supported by the explanation given by @DanyloVolokhSubjoinder
That's the case of you use hasStableIds with array indices returned from getItemId, yes. I admit, the wording isn't great. Edits welcome :)Jessi
And just to be clear, as per the docs here it should return true when an id is guaranteed to refer to a particular unique object, such that a change in id signifies an object changed and an id remaining the same means it is not some new object returning the same id in which case the view would have to be updated and the method would be required to return false.Hortensiahorter
Without it, the ListView has to recreate all Views On the contrary, Views are in a RecycledViewPool and should be recycled. To me the advantage of stable Ids is that you don't need to bind them again. Or do I miss something ?Illjudged
A
21

If hasStableIds() returns false then each time you call notifyDataSetChanged() your Adapter will look at the returned value of getItemId and will eventually call getView(int position, View convertView, ViewGroup parent). If hasStableIds() returns true the this will only be done when their id has changed.

Using this technique you can easily update only one Item in the ListView

If you implement getItemIdcorrectly then it might be very useful.

Example :

You have a list of albums :

class Album{
     String coverUrl;
     String title;
}

And you implement getItemId like this :

@Override
public long getItemId(int position){
    Album album = mListOfAlbums.get(position);
    return (album.coverUrl + album.title).hashCode();
}

Now your item id depends on the values of coverUrl and title fields and if you change them and call notifyDataSetChanged() on your adapter, then the adapter will call getItemId() method of each element and update only those items which id has changed.

This is very useful if are doing some "heavy" operations in your getView().

Akene answered 4/4, 2015 at 13:22 Comment(7)
I think, you meant "If hasStableIds() returns true", right?Dungeon
No, I meant "false". When ids are not stable. (Mutable)Akene
Regarding your example, what would happen if hashCode() returns the same number for 2 different strings (i.e. you have a hash codes collision)? And generalizing, if your getItemId(int position) returns not unique IDs. how it affects the ListView?Epiblast
This way I assume you will have incorrect behavior. You should return unique id for unique items. Hash code is not ideal. But either way "long" is limited so we cannot guarantee the id to be absolutely unique.Akene
-1. This answer is completely wrong. The RecyclerView can only avoid unnecessary work in this way when items have stable ids and you call setHasStableIds(true). The sample code will not work the way the writer says it does under any circumstances. hasStableIds() asks a question about item identities, not about item values. If hasStableIds() returns false, the adapter must recreate all views on every update, as it cannot assume list items with the same ID correspond to the same data.Starcrossed
In addition to @ClementCherlin 's comment, hashCode method is unreliable to use as identifier. Remember that hashes do not guarantee uniqueness, but rather inability to find a collision. Collision can be very common in hash functions and for large datasets, they could cause inconsistency between data provided and data displayed.Witticism
It looks like a simpler version of DiffUtilsMyongmyopia

© 2022 - 2024 — McMap. All rights reserved.