Have you been experiencing some irregularities in your recyclerview? Issues like:
- The recyclerview pre-setting the (wrong) value of some of the views in the list.
- Some views being visible when they shouldn’t be and vice versa.
and so on…
99% of the time, this is a problem with recyclerview recycling the views. The 1% percent left could come from human error.
Let’s quickly revisit how RecyclerView works.
How does RecyclerView work?
RecyclerView can easily be called the better ListView. It works just like a ListView — displays a set of data on the screen but uses a different approach for the purpose. RecyclerView, as its name suggests, recycles views once they get out of scope (screen) with the help of ViewHolder pattern.
So how does this affect your app?
Just like I wrote up there, RecyclerView recycles the views once they get out of the screen. While trying to reuse the cache view, binding with the new data sometimes goes wrong. The RecyclerView either retains the old data for the view or fail to reset the view.
Solution
There is an okay solution and there a boom! solution.
1. Reset your views
This may seem trivial but really, a simple thing like resetting your view to their default state during binding could save you a lot of time.
fun bind(question: Question) { itemView.rb1.isSelected = false itemView.rb2.isSelected = false itemView.rb3.isSelected = false itemView.rb4.isSelected = false //Other code goes here }
What we are basically doing is making sure that we have a default state for the views when our actual data is not being set. This implementation would be different for your different use cases.
2. Use the god-method – Disable recycling
For a situation whereby the first solution above doesn’t work, there is a solution that works like boom!
Add the following line of code in your bindViewHolder() method:
holder.setIsRecyclable(false)
override fun onBindViewHolder(holder: QuestionsViewHolder, position: Int) { holder.setIsRecyclable(false) //Disable recycling val question = questions[holder.adapterPosition] holder.bind(question) }
What this line of code does is to basically disable recycling for the recyclerview. That way, new views are created for each list item.
Works like charm!
But isn’t this against what RecyclerView is made to do?
You may want to ask the question, isn’t this against what the recyclerview is made to do?
Google deliberately created RecyclerView.ViewHolder.setIsRecyclable()
for cases where RecyclerView should not recycle views or recycling views have adverse effects.
NB:
- A way you can make it more efficient is to take note of which views to recycle and which not to recycle, by handling that based on the number of items in the list.
- If you are working on an interactive list like mine in the example above, you can find a way to save and keep track of user selection (or any other form of interaction with the views). Like the options chosen by the users as it is in my example above. Reason being that the recyclerview uses entirely new views when scrolling through the list.
Voila!
Thanks for reading. Also, let me know if the solution works for you. And you can give suggestions of other solutions that might have worked for you.
Peace out ✌
Thanks a lot Emmanual. I really appreciate this
You’re welcome bruv!
Great post Emmanuel!…looking forward to see more of this!
Thank you.
Nice one boss!
Thanks!
Thanks buddy! You helped me a lot with the understanding of the RecyclerView. I already thought I had a good implementation, but now is awesome!
Thanks!
Hi A HAVE the same problem bu youy solution dont work for me
thanks for hep