RecyclerView Optimization - Scrolling Performance Improvement
- Authors
- Name
- Amit Shekhar
- Published on
I am Amit Shekhar, Co-Founder @ Outcome School, I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.
Join Outcome School and get high paying tech job: Outcome School
Before we start, I would like to mention that, I have released a video playlist to help you crack the Android Interview: Check out Android Interview Questions and Answers.
In this blog, we are going to learn how to optimize the RecyclerView performance in Android. With these optimizations, we can make the RecyclerView scrolling smooth.
When we implement RecyclerView in our Android Application, sometimes, we face problems like: The RecyclerView items are not scrolling smoothly. It leads to bad user experience as it seems that our Android App is laggy.
Let's see what are the things which we can do to improve the performance of the RecyclerView and hence, we get the smooth scrolling.
RecyclerView Optimization Techniques
Let's get started
Use Image-Loading Library
As the Garbage Collection(GC) runs on the main thread, one of the reasons for unresponsive UI is the continuous allocation and deallocation of memory, which leads to the very frequent GC run. By using the bitmap pool concept, we can avoid it.
The best part is that Image-Loading libraries like Glide, Fresco uses this bitmap pool concept. So, always use Image-Loading libraries.
Delegate all the image-related tasks to these libraries.
If you are curious to know: How The Android Image Loading Library Glide and Fresco Works? Read here.
Set Image Width and Height
If our image width and height are dynamic(not fixed), and we are getting the imageUrl
from the server.
If we do not set the correct image width and height prior, the UI will flicker during the transition of loading(downloading of image) and setting of the image into the ImageView(actually making it visible when downloading completes).
So, we should ask our backend developer to send the image size or the aspect ratio, accordingly, we can calculate the required width and height of the ImageView.
Then, we will be able to set the width and height prior only. Hence no flickering. Problem Solved!
Do less in onBindViewHolder method
Our onBindViewHolder method should do very less work. We should check our onBindViewHolder method and optimize it. We can see the improvement in our RecyclerView by doing so.
Use Notify Item RecyclerView API
Whenever we have the use-case of the removal, the updation, the addition of item, use the Notify Item API.
adapter.notifyItemRemoved(position)
adapter.notifyItemChanged(position)
adapter.notifyItemInserted(position)
adapter.notifyItemRangeInserted(start, end)
In case, we are forced to use notifyDataSetChanged()
based on our use-case, we can try the setHasStableIds(true)
.
adapter.setHasStableIds(true)
It indicates whether each item in the data set can be represented with a unique identifier of type Long.
Even if we call the notifyDataSetChanged()
, it does not have to handle the complete re-ordering of the whole adapter because it can find if the item at a position is the same as before and do less work.
Avoid a nested view
If possible, we should avoid a nested view and try to create a flat view wherever possible. Nesting reduces RecyclerView performance. Flat View improves performance.
Use setHasFixedSize
We should use this method if the height of all the items is equal. Add the below and check the performance.
recyclerView.setHasFixedSize(true)
Use setRecycledViewPool for Optimizing Nested RecyclerView
As we know that the RecyclerView works on the principle of "Reuse View Using Pool" wherever possible.
If we have the use-case of Nested RecyclerView.
- OuterRecyclerView
- InnerRecyclerViewOne
- InnerRecyclerViewTwo
But by default, the optimization works for that particular RecyclerView because that particular RecyclerView has its own View Pool.
The pool does not get shared between two RecyclerViews having the same types of views.
So, what we can do is that we can create a single ViewPool and pass it to all the inner RecyclerViews so that it gets shared like below:
class OuterRecyclerViewAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// code removed for brevity
private val viewPool = RecyclerView.RecycledViewPool()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
// code removed for brevity
viewHolderOne.innerRecyclerViewOne.setRecycledViewPool(viewPool)
// code removed for brevity
viewHolderTwo.innerRecyclerViewTwo.setRecycledViewPool(viewPool)
}
// code removed for brevity
}
This will improve scrolling performance as it will start reusing the view from the shared ViewPool.
Use setItemViewCacheSize
We can experiment by setting the ItemView Cache Size.
recyclerView.setItemViewCacheSize(cacheSize)
As per the official documentation: It sets the number of offscreen views to retain before adding them to the potentially shared recycled view pool. The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.
It means that when we scroll the RecyclerView such that there's a view that is just barely completely off-screen, the RecyclerView will keep it around so that we can scroll it back into view without having to call the onBindViewHolder()
again.
Generally, we do not change the size of the View Cache, but experiment with it, if it works for you, implement it.
These are things that we can do to improve the performance of RecyclerView. That's it for now.
Show your love by sharing this blog with your fellow developers.
Prepare yourself for Android Interview: Android Interview Questions
That's it for now.
Thanks
Amit Shekhar
Co-Founder @ Outcome School
You can connect with me on:
Follow Outcome School on: