Android Data Binding + ListAdapter

How to say good bye to binding logic boilerplate

Fred Porciúncula
ProAndroidDev
Published in
4 min readAug 28, 2018

Data Binding is a pretty powerful library that I've shamefully ignored for most of my time as an Android dev (most likely because it used to be a little contradictory). I've been reading a lot about it, and I naturally stumbled upon George Mount's blogposts. The article that really caught my attention was this one about Data Binding on a RecyclerView:

That was the moment I realized how great Data Binding can be, and being an avid user of ListAdapter, I thought things could get even better if I added it to the mix. This will be a brief blogpost about how we can make the best out of Data Binding and ListAdapter in order to reduce boilerplate and just make our code simpler and prettier.

Let's get started

… but first, just in case you don't know what a ListAdapter is:

RecyclerView.Adapter base class for presenting List data in a RecyclerView, including computing diffs between Lists on a background thread.

It's a base Adapter that automatically updates itself (with free animations!) when the list changes. Calling notifyDataSetChanged() and its friends is now a thing from the past — all you need now is to call submitList() passing the updated list. If this is new to you, it might be a good idea to take some time and learn more about it — the documentation is pretty good and might actually be the only resource you'll need.

Now back to the important stuff.

The main idea of the blogpost I just mentioned above is how we can come up with a generic ViewHolder that can be reused for any Adapter in our app. It assumes the ViewHolder will only need a single data object for the binding (which is definitely a good practice anyway). This object is the parameter of the bind() method, and all we do with it is set it as the variable for a ViewDataBinding we receive as a constructor argument. Through a clever naming convention trick we'll be able to make this ViewHolder work wherever we want (more on that later):

Yes, this tiny class has the potential to replace most ViewHolders you've written so far. The original code fulfils our purpose here, so we won't change a thing. If you want to understand that executePendingBindings() line, head out to the original post for a great explanation.

Next, we can create a base Adapter that will have most of the boilerplate we'll need for any Adapter we'll write. Our DataBindingAdapter will be a little different here because it'll extend ListAdapter:

That's it, a super simple class — even simpler than the original thanks to the ListAdapter. There's an important assumption we make there: the layout id used by the Adapter to inflate the layout is the viewType, so any child Adapter will need to override getItemViewType() to indicate which layout should be inflated. This assumption is another good practice that is even reinforced in the documentation.

Consider using id resources to uniquely identify item view types.

Now let's say we want to show a list of books. Given those two classes we just wrote, let's see how our BooksAdapter would look like:

Thanks to our base classes, the only things we'll need to worry about when creating an adapter is writing the DiffUtil.ItemCallback required by the ListAdapter and indicating the layout id we want to inflate through the getItemViewType() method. Of course we also need special attention in our layout file:

The important thing here is that the variable name must match whatever name we're using in the DataBindingViewHolder — in this case it's item. The rest is simple and standard Data Binding code.

What about Adapters with different ViewHolders?

Well, I'm glad you asked. Usually, the only thing we'll have to change is how we're implementing getItemViewType() in the Adapter, but normally the DiffUtil.ItemCallback will have to change too.

Let's say our list of books will have sections, which will naturally be represented by a completely different layout file. We'll make sure our Book model and our new Section model share an interface, let's say Listable, just so we can have them on a same list. Sealed classes would also be a nice option here, but let's not get into that.

This is how our BooksAdapter would look like:

And there's nothing special when we want to use this adapter in an Activity, for instance:

What I like most about all this is that once everything is setup, creating another Adapter is as easy as writing how to differentiate the items in the list (so ListAdapter can do its job) and what layouts we want to inflate. It's boilerplate proof and it feels like we're only writing code that actually matters.

If you are like me and haven't given Data Binding much love, I hope what I wrote here may change that a little. Data Binding is pretty awesome, my experience with the new compiler has been great so far, and it's been a while now that Data Binding and Architecture Components can hang out together. I hope you can take advantage of it as much as I have!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Responses (10)

What are your thoughts?