Android — RecyclerView using MVVM and DataBinding

A few days ago I wrote an article on how to implement form validation using MVVM and data-binding. The idea here wasn’t to teach form validation, MVVM or data-binding, but rather to give a comprehensive example of how MVVM with data-binding can be used for complex requirements. I got a lot of questions from people about how can we have separation of concerns between ViewModel, Model and UI in the case of something like a RecyclerView. The short answer is that it’s possible, though it requires some thinking ahead.

RecyclerView functionality

Like before, while I try to provide a list of techniques to use, it’s by no means a full list. The hope is to empower you to a point where you can fit in whatever requirements you have while respecting the MVVM pattern.

That being said, our app will sport the following features:

  • When the app loads, a list of dog breeds will be loaded from an API call.
  • When the list is displayed we will request images for each breed as it’s loaded by the RecyclerView.
  • When a dog breed is clicked, we propagate the click to the activity.

Show me the code

In that code repo, you’ll find 2 implementations, each slightly different. The master branch has an implementation that aims to have to have all functionality exposed to the Views through the ViewModel while method_alt has an alternate implementation that in some senses simplifies the code, but the downside is that the View is aware of the Model object backing it making the code more tightly coupled and IMHO contrary to the MVVM design.

Code explained

Model explained [code]

The main thing to note here is that the fetch functionality is encapsulated in the model. When we want to fetch a list of dog breeds, the model object DogBreeds has a fetch method. When we want to fetch the images for a dog breed, the DogBreed (singular, spelt without an “s”) has a fetch method to fetch the list of dog images.

In the instance of DogBreeds, the model object sets the list of breeds within itself, however the Activity is the one listening for a change to the list of dog breeds. The idea here is that the Model will not automatically tell the RecyclerView adapter to update itself. Instead it, a View, such as an Activity or Fragment attaches an observer to the dataset and tells the ViewModel to update the adapter if needed. This is important, because we need to have a degree of separation between the Model and the View and if the Model directly updates the View, then a dependency on that particular View is created within the Model.

When a DogBreed is displayed by the RecyclerView, the RecyclerView in method_alt calls the fetch method for the images directly, in master, the RecyclerView adapter goes through the ViewModel to tell the DogBreed object to fetch images. I like the approach of going through the ViewModel because under MVVM, the ViewModel is meant to expose functionality in the Model to the View. Hence, this feels more pure to me. When an the list of images is fetched, the ViewModel stores it in an Observable map. Then the layout fetches the images from this map through data-binding. I also like this approach because the image URL’s are retained through orientation changes (thanks to the Android LifeCycle components handling this automatically) and so there is no need to fetch the images again.

CustomViewBindings explained [code]

The code here is designed to allow you to bind a RecyclerView to an adapter without having to hold a hard reference to RecyclerView in the ViewModel. The main reason you don’t want to do this is that while the Adapters functionality may be reusable, you may choose to use it with a different RecyclerView so you want to move this code out from your ViewModel. You can see in the layouts for the RecyclerView and the list items how these are used.

ViewModel explained [code]

As I have mentioned repeatedly, the ViewModel’s job is to expose functionality to the View and maintain some state for the View. So what you see here are the various methods that are called either from the Activity/Fragment or from the layout/data-binding to get or set data.

Activity explained [code]

The main take away here is that the Activity triggers the ViewModel to fetch the list of DogBreeds and then observers for a change to the list of dog breeds. When it receives a change to the list, it asks the ViewModel to update the adapter with the new dog breeds. This is important because the Activity is the View. It knows the data it needs to display and should be listening for when that data changes or becomes available.

RecyclerView adapter [code]

This code is fairly stock standard. The only thing out of the ordinary is that the Adapter is not directly holding a reference to the data it is displaying. Instead it knows of the ViewModel and passes this down to the data-binding where the layout requests the correct object based on its index. This is slightly different from the method_alt implementation where the DogBreed object is directly accessed by the adapter and added to the data-binding.

Finally

Hopefully there is enough there to help you use a RecyclerView with Data Binding and the MVVM pattern no matter what your requirements. One thing is for sure in order to build great Android apps, read more of my articles.


Yay! you made it to the end! We should hang out! feel free to follow me on Medium, LinkedIn, Google+ or Twitter.