Pragmatic Approach to Android MVVM: Part 2

Brian Lee
3 min readJan 29, 2018

--

In the previous post, we went over implementing permission request flow for an Image Analyzer app. In this post, we’ll cover how we might apply MVVM to load photos into RecyclerView:

Plan of Attack

As mentioned in the previous post, we want to avoid fighting the platform. Instead, we will try to find a good balance of utilizing Android components and ViewModel. To load the photos in RecyclerView, we’ll to the following:

  1. Use CursorLoader to load thumbnails from MediaStore
  2. Load the data into RecyclerView.Adapter
  3. Bind a ViewModel to each item View
  4. Set the data in ViewModel in RecyclerView.ViewHolder

Loading Thumbnails

When READ_EXTERNAL_STORAGE is acquired, GalleryViewModel will send LoadPhotosEvent via the EventBus to GalleryActivity. At this point, we can use LoaderManager to load the thumbnail data, and pass it to the ThumbnailAdapter. The relevant code is highlighted in the snippet below:

In ThumbnailAdapter, let’s take the Cursor as is and use it:

Item Layout and ViewModel

Now that we have the cursor loaded, we want to do the following:

  1. Set a square thumbnail layout in the item view
  2. Load the image using Glide
  3. When the image is clicked, send out an event to view the image

We’ll use a ConstraintLayout to create the square ImageView, use custom binding to load the image via Glide, and use EventBus to handle image click.

The corresponding XML layout is below:

The custom binding to handle image loading via Glide:

And finally, ThumbnailViewModel:

The ViewImageEvent above has some extra data that the next Activity needs to load the full image and to create a Scene Transition Animation.

Creating and Binding ViewHolder

We now have the Adapter in place to load and set the data, and a ViewModel to load and represent the UI. The next step is to set up onCreateViewHolder and onBindViewHolder to connect the Adapter and the ViewModel. This is pretty straight forward.

In ThumbnailViewHolder, whenever the data is changed, update the ViewModel data and execute the binding:

And in ThumbnailAdapter, set the ViewModel and the Binding in onCreateViewHolder, and set the item data in onBindViewHolder:

Testing

We have now separated the responsibilities as follows:

  1. GalleryActivity handles loading of the Cursor
  2. ThumbnailAdapter handles reading the Cursor and setting the current item data on the ViewHolder
  3. ThumbnailViewModel handle the View representation and the image click

This makes the ThumbnailViewModel very testable:

In this example, we’ve used a simple RecyclerView with only a single element type. In a typical production app, there may be many different types of items in a single RecyclerView, resulting in multiple ViewHolders and ViewModels. With this approach, all of these individual items in the RecyclerView can be unit tested and even reused.

We’ll go over making the network request to analyze the image in the next post.

Thank you for reading! Feel free to say hi or share your thoughts on Twitter @hiBrianLee or in the responses below!

Full project source code: https://github.com/hiBrianLee/ImageAnalyzer

Other parts of this post:

Some of my other posts:

--

--