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.

Leave a rating/review
Download materials
Save for later
Share

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.
Note: This tutorial assumes you’re familiar with Android Studio and the basics of Android development. If you’re new to either, read through Beginning Android Development and Kotlin for Android: An Introduction before continuing.

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.

Bring Cookies feature set: add a new item, mark items as done and randomize list

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.

The directory structure of the project.

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 of id, its value, the timeStamp 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.
Note: In this tutorial, you’ll use RecyclerView to display your grocery list. To learn more advanced content about how to use this view, check out Android RecyclerView Tutorial with Kotlin or Intermediate RecyclerView Tutorial with Kotlin.

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.

Distributed the lists: ANDROID and DIORDNA into a matrix to apply the Myers algorithm.

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.

The Myers algorithm applied to the lists: ANDROID and DIORDNA.

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.

Note: You can find more information about the Myers algorithm in this blog post from James Coglan.

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 from androidx.recyclerview.widget.
  • ListAdapter from android.widget.

Import the first one, androidx.recyclerview.widget, to successfully access the adapter.