Should Recyclerview Adapter have the responsibility of data in MVVM architecture?

Paul Stanescu
4 min readSep 23, 2019

--

I’m going to start the post by answering the question from the title and the answer is no. Within any clean architecture, the View should know only to draw.

On one of my previous posts, I tried to underline the crucial importance of having a clear and clean architecture in order to achieve the quality target. On that post I said: “Having a good design means taking into consideration the future growth, eliminating the impact, high cohesion and low coupling.”

Warm-up

Android apps, mainly, are frontend apps, they are consuming web services and present formatted date to the user. Taking this into consideration we understand that the best architecture pattern is one that can react fast to design changes.

In terms of abstracting the view’s states and behavior is pretty similar to what MVP (Model — View — Presenter) does. Both MVP and MVVM decouple the presentation logic (and also business logic) from View then it becomes independent from a specific UI platform. MVVM pattern helps you to simplify the event-driven programming of user interfaces.

In MVP the View is actually your presentation layer while Presenter handles the app’s business logic. In MVVM the ViewModel is the right place to put the logic for data presentation, while the View is the interface allowing users to interact with the app.

Problem — Solution

Let take the following example: we want to display a list of users, each user having certain characteristics. The logical steps to implement this simple functionality is to:

  • create the view (Activity or Fragment). Withing the inflated layout we will have at least a recyclerview element, besides other elements that can be part of the main view;
  • create the repository and define the method which will retrieve the list of users
  • create the viewmodel having access to the repository and also a function which calls the repository in order to get data.
  • when data is available, the adapter attached to the recyclerview will draw the items part of the user list.

Until now, I think and I hope that everything is pretty clear. What’s next? We have to decide how we are going to provide data to the adapter. In order for the adapter to be able to display the users should have access to data received from the repository.

Now, we have 2 solutions:

  1. As you have already guessed one solution is to define and store a list within the adapter, such as:
class UserAdapter(): RecyclerView.Adapter<UserViewHolder>() {    var userList: List<User>? = null
...
}

and from the view, we will create an instance of this adapter and we will attach it to the recyclerview list.

Of course, this solution is working but doesn’t respect one of the simple OOP’s concept, single responsibility. The adapter knows to do too many things, it manages data (the list of users) and refreshes views (draw items).

We will park this solution as a bad one and we will try to define a better one.

2. To define the second solution, which should be the right and the clean one we will try to define some checkpoints:

  • the adapter should know what it has to draw but not directly
  • then we should have “someone” to tell the adapter what it has to display
  • does it sound like a contract?
  • yes, bingo, a contract will be the “someone”
  • what we know until now: we have an interface where we will define all methods which are required by the adapter to be able to do its work; the adapter should have a reference to this interface;
  • pretty clear but where is the concrete implementation of the interface?
  • where? where you have all data that you need to display the entire list of users, within the viewmodel.
  • let's draw a diagram and explain it afterward
UML Diagram

Explanation:

  • View has an instance of RecycledView, Adapter and obviously ViewModel;
  • ViewModel gets data from Repository and because the repository is injected on the constructor the relation is aggregation; ViewModel also implements the interface UserAdapterDataModel and in this way provides needed information to the adapter (trough interface);
  • Adapter knows only to draw but in order to be able to display the items properly, it needs to know, at least the size of the list and the item for each position; that information is coming from userAdapterDataModel which should be defined as a required parameter on the constructor; the relation between Adapter and UserAdapterDataModel is a strong one, the Adapter couldn’t exist without having an instance of an object which is an UserAdapterDataModel, due to this reason the relation is composition.
class UserAdapter(private val dataModel: UserAdapterDataModel): RecyclerView.Adapter<UserViewHolder>() {...}

Summary

On the first solution, Adapter was control data and view of RecyclerView, but it has two roles, data and view at the same time which generated a conflict to what clean architecture means.

On the second solution, which solved our problem, I used an interface for definition of adapter’s role. The outcome was: ViewModel accesses only Repository and provides data to the adapter through the interface it implements. The ViewModel controls the data and the Adapter is allowed only to draw without knowing the data directly.

Just code it!

--

--