How to Extend the ListAdapter with a Header View

Coding Ideas Featured

For all Android app developers tackling the issue of scrolling, read on. In this article we share how to extend the ListAdapter with a Header View in Android.

RecyclerView: Adapting to change

If your Android app has to display a scrolling list of elements, then you are most probably going to be using a RecyclerView (especially if it is based on a large set of data).

The RecyclerView in Android uses several components that work together to display your data efficiently so that your app will have super silky-smooth scrolling that your users will appreciate.

A LayoutManager, as the name suggests, decides how best to layout your data (e.g. in a simple list or grid, or maybe a staggered grid) and it provides the actual views to the RecyclerView to display.

The views themselves are represented by view holders which extend a ViewHolder object. Each view holder is responsible for displaying a single item of data from the list.

The RecyclerView only creates as many view holders as are necessary to represent the data currently being displayed on the screen. As users scroll through your list, the RecyclerView takes any view holders no longer being displayed and re-uses them, rebinding them to the data that is scrolling onto the screen.

The RecyclerView delegates the management of the view holders to an Adapter which creates the view holders as needed. The adapter is also responsible for binding a view holder to the right data item in the list. The adapter needs to be told when the data items are changed (inserted, deleted or updated) so that it can communicate that efficiently to the RecyclerView.

What’s the difference?

The standard classes provide most of the common functionality needed; you’ll just need to create a view holder that can display an item of your data, and an adapter that creates and binds viewholders.

However, simple adapter implementations often aren’t very efficient. The adapter needs to be told when the data has changed and, because sometimes it isn’t a trivial job to work out what has changed, it was often easiest for a developer just to inform the adapter that the whole list had changed rather than the individual data items.

The support library in August 2016, version 24.2.0, introduced a new class DiffUtil that could efficiently calculate the differences between two collections of data. It could also dispatch a list of update operations to convert one list into another in a manner convenient for Adapters to communicate those update changes to the RecyclerView. Although a really cool tool, it wasn’t immediately obvious how/when it should be used and developers often always take the path of least resistance (a.k.a. the easiest route).

Introducing the ListAdapter

And so recently the support library, version 27.1.0 (Feb 2018), provided a new tool for developers working with RecyclerViews - a new ListAdapter. (It’s found in the package or, as of Google I/O 2018, repackaged under androidx.recyclerview.widget and is not to be confused with the older ListAdapter class that’s been around since the beginning of Android and does something completely different!)

What Does the ListAdapter in Android Do?

The new ListAdapter makes things easy for developers. It automatically uses the DiffUtil class for calculating list differences and it also performs the diff on a background thread, as it can sometimes be CPU intensive.

Both these things help the RecyclerView animate content changes automatically without doing too much on the UI thread - great stuff.

If you want to know more about how to use a ListAdapter, definitely take a gander at this Medium article by Craig Russell. Russell explains how to use a List Adapter with Kotlin and LiveData.

Header View: What’s the Issue?

It is a common requirement to have an app design requiring a header view at the top of a list of scrolling data that scrolls with the list contents. When implementing this in an adapter, a fairly standard pattern is to pretend the header is part of the list of data, so that the adapter:

  • Reports an extra item when asked how many items are in the list

  • Returns the header item when asked for the first item in the list

  • Applies an offset when notifying the RecyclerView which items have changed.

However, when working with a ListAdapter, this standard pattern doesn’t work. The ListAdapter handles the diff calculations and updates notifications itself so that you can’t make it pretend there is a header row.

The Solution: ListAdapterWithHeader

My solution was to create an abstract class ListAdapterWithHeader that I could extend when creating my own adapters. ListAdapterWithHeader is based on the ListAdapter, but you can tell it how many header items there are before the list of data starts.

Here is an ExampleAdapter that extends and uses the ListAdapterWithHeader:

1. DiffUtil uses Eugene W. Myer’s difference algorithm to calculate the minimal number of updates to convert one list into another. Here's a link to his research paper if you’re interested

Fast Track Guide

Here's how to create a ListAdapterWithHeader (inspired by the support library ListAdapter) and an ExampleAdapter that uses it for those who don’t have time to read the whole article.

In Summary

Thanks for reading. I hope you found this article helpful. For another article on scrolling and headings, check out our post on UICollectionView.

Looking for something else?

Search over 400 blog posts from our team

Want to hear more?

Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!