I am working on an app where I am trying to populate a list using RecyclerView and recycler adapter as well. But when I scroll through the list quickly sometimes values on t
Overriding getItemId
and getItemViewType
fixed the problem for me.
adding this in the adapter solved the problem
@Override
public int getItemViewType(int position)
{
return position;
}
The items are getting shuffled because you're not updating the item's ViewHolder properly inside the onBindViewHolder()
. To understand why this behavior occurs, you need to know how exactly the RecyclerView recycles the list items.
By default, the RecyclerView will only create the number of items that can be shown on the device's screen. This means that even if there are hundreds or thousands of list items in the list, if the device can only show 10 items on its screen at a time, then approximately only 10 items will be created and stored in the main memory(RAM). When the screen is scrolled these 10 items will be updated with the new content instead of creating a new one. In the below image you can see the 1st item getting recycled by just updating the text from ABC to XYZ.
Image Source: Google Codelabs
More specifically, while scrolling, instead of garbage collecting the scrolled off item's ViewHolder and creating a new one, the RecyclerView will use the same scrolled off item's ViewHolder and updates it with the upcoming new list item's properties. (A ViewHolder is something that holds the views of a particular list item and properties that describe it)
This update handling is done by overriding the onBindViewHolder()
method which gets called whenever a new item needs to be shown on the screen. The reason why the values on your list shuffles have something to do with how you're updating the ViewHolder inside this method. As I said before since the list items get recycled, while scrolling the list the ViewHolder that you obtain as a parameter for onBindViewHolder()
will already be assigned with some other list item's properties. So, you need to make sure that all the properties of this ViewHolder are either replaced according to your new list item's property or reset back to the default one. To do so, check whether you're using any conditions inside this method and make sure that you add a default condition to it that will reset that particular view's property to the default one.
Example:-
if (<CONDITION>) {
holder.textView.setText("New Text")
} else {
// reset
holder.textView.setText("Default Text")
}
Finally, I strongly recommend you to not use the other solutions that suggest you to use unique view types for all list items by simply assigning the position number to the view type by overriding getItemViewType()
. Doing so will make the RecyclerView to think that all the items in your list have a different type of layout and so each one will be created separately from scratch. This will result in increasing your app's main memory usage and also the load time of your activity or fragment that contains the RecyclerView.
In case if you're still not having a clear understanding of RecyclerView's working then I'd suggest you to go through the RecyclerView Fundamentals codelab by Google. In this codelab they've even exclusively addressed this recycling issue in Step 6 of its first task.
Just Override these methods in your adapter class:
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
This link will help you to get the understanding of the concept behind.
How to fix Recyclerview shuffling issue
Just have to override two methods in your Adapter and it will solve your issue.
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}