Speed up Your Android RecyclerView Using DiffUtil
Learn how to update the Android RecyclerView using DiffUtil to improve the performance. Also learn how it adds Animation to RecyclerView. By Carlos Mota.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Speed up Your Android RecyclerView Using DiffUtil
25 mins
- Getting Started
- Understanding the Project Structure
- Getting to Know DiffUtil
- Understanding the DiffUtil Algorithm
- Creating Your RecyclerView With ListAdapter
- Adding DiffUtil to ListAdapter
- Updating ListAdapter’s Data References
- Accessing ListAdapter’s Data
- Comparing References and Content
- Using DiffUtil on a Background Thread
- Using DiffUtil in Any RecyclerView Adapter
- Using Payloads
- Animating Your RecyclerView With DiffUtil
- DiffUtil in Jetpack Compose
- Where to Go From Here?
Android RecyclerViews displaying some sort of list are part of almost every Android application in the real world. Lists hold a lot of information, so it’s important to provide a smooth experience both when a user is scrolling through a list and when its content is updated. DiffUtil is a utility class developed to help with this, and Android RecyclerView using DiffUtil provides this feature.
In this tutorial, you’ll build a grocery list app. It uses DiffUtil to avoid redrawing all the cells in a list when only a subset of its data changes. During this process, you’ll learn:
- How to implement DiffUtil with ListAdapter.
- To convert your ListAdapter into any class that extends RecyclerView.Adapter.
- To use payloads.
- How DiffUtil adds Animation to RecyclerView.
Getting Started
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
You’ll find two projects inside the ZIP file. Starter has the skeleton of the app you’ll build, and Final gives you something to compare your code to when you’re done.
In the image above, you see a grocery list. You can probably relate to returning home from the store, only to realize you forgot to buy everything you needed. The best approach is to write a shopping list in advance, but sometimes those get left at home. But you most likely always have your phone with you.
So, you’re going to create BringCookies, a grocery list app that helps you keep track of everything you need to buy on your next trip to the store. And it has a bonus feature! The item Cookies is always on the list, because there’s always room for more cookies. :]
But first, you’ll take some time to understand the project structure.
Understanding the Project Structure
Open the Starter project in Android Studio and wait for it to synchronize.
You’ll see a set of subfolders and other important files:
-
adapters: Contains the
RecyclerView
adapter and a set the utilities used to select one or more items from the list. -
model: Contains the
Item
data object to represent an item.Item
consists ofid
, itsvalue
, thetimeStamp
of when it was created and a Boolean flag —done
— that indicates if item was checked or not. - MainActivity: The app’s single activity.
- MainFragment: Responsible for displaying the grocery list to the user and providing a set of mechanisms with which the user can interact.
- Utils.kt: This file contains a set of utility methods you’ll use throughout the project. Namely, you’ll use these to save and load your grocery list into and from shared preferences and format a note timestamp to an easily readable date.
Moving on, it’s time to learn more about DiffUtil.
Getting to Know DiffUtil
The DiffUtil utility class exists to improve RecyclerView’s performance when handling list updates. Even if associated with this UI component, you can use it in any part of your app to compare two lists of the same type. In the case of this app, you’ll want to check the differences between two lists of type Item.
For the algorithm used by DiffUtil to work, the lists must be immutable. Otherwise, if their content changes, the result might be different than expected. Hence, to update an item in the list, create and set a copy of that element.
Understanding the DiffUtil Algorithm
To see the difference between two lists — in the case of RecyclerView, the one that you’re already showing and the one that you want to show (when any of items in the list changes) — DiffUtil uses the Eugene W. Myers difference algorithm. This calculates the difference between both sets of elements.
Myers algorithm does not handle elements that are moved so DiffUtil runs a second pass on the result that detects which elements moved.
This image has two lists of words spread through a grid: ANDROID horizontally and DIORDNA vertically.
The algorithm calculates the shortest path from one list to the other. Diagonals are free steps, and for this reason, they don’t count for the number of iterations required.
Starting on (0, 0), which corresponds to the character ‘A’, the Myers algorithm goes through each point in the matrix, looking for the shortest path to transform one list into the other.
From this initial point, it can go down to (0, 1), or right to (1, 0):
- From (0, 1), it can go to (0, 2) or (1, 1).
- From (1, 0), can go to (1, 2) or (2, 0).
At this last coordinate, (2, 0), there’s a diagonal insight, which means it’s possible to reach directly to (3, 1), thereby saving a couple steps.
Following this path, you can go from (0, 0) → (0, 1) → (1, 0) → (3, 1), skipping (2, 0) and (3, 0).
The algorithm will analyze all the possible paths, selecting the shortest one to convert one list into the other. In this example, it takes eight iterations.
Creating Your RecyclerView With ListAdapter
ListAdapter
is an extension of RecyclerView.Adapter
that requires initializing DiffUtil.ItemCallback
or AsyncDifferConfig
. It provides a set of methods that allows you to easily access the adapter’s data, but you can use any available adapter.
So first, open MainAdapter.kt.
This class extends the default implementation of RecyclerView.Adapter
. Change it to use ListAdapter
:
class MainAdapter(val action: (items: MutableList<Item>, changed: Item, checked: Boolean) -> Unit) : ListAdapter<Item, MainAdapter.ItemViewHolder>()
Android Studio prompts two imports:
-
ListAdapter
fromandroidx.recyclerview.widget
. -
ListAdapter
fromandroid.widget
.
Import the first one, androidx.recyclerview.widget
, to successfully access the adapter.