Image by andrekheren from Pixabay

Are you tired of rewriting RecyclerView Adapters?

Emmanuel Ortiguela
3 min readDec 30, 2019

--

Me too! So I decided to create Adapt in an effort to alleviate the pain.

What is Adapt?

What if told you that creating adapters can be as simple as:

Adapt is a DSL that attempts to standardize RecyclerView.Adapter creation by leveraging Android’s Data Binding framework.

How do I use it?

The simple case:

The DSL has several adapter(). For the simplest case, an adapter that handles one row type, the adapter can be defined by:

ComicModel is a data class that implements Identity. Identity allows the consumer to determine how areItemsTheSame() will be computed.

BR.comicModel is the data binding variable that represents the model to be bound. This is automatically generated by Data Binding when you define the variable in the xml layout file:

R.layout.comic_cell is the layout for the item that Data Binding will inflate.

What if I need a click listener added to the whole row?

There is an overload for adapter() that takes in a function that is applied as the click listener for the row:

What if I need a click listener added to a particular item within the row?

There is an overload for adapter() that takes in a lambda that gives access to the ViewDataBinding for the row’s layout and the model:

The not so simple case:

There is an overload for adapter() that allows the caller to define an adapter with multiple ViewHolders in a “concise” manner:

As you can see, TestFragment.adapter()is an extension function for the class that will use the adapter. This is done so the adapter definition can be extracted to its own file. Then the caller can get an instance of the adapter via:

It is worth noting that Header and Content belong to the sealed class Model which implements Identity

holder() is a function that eases the creation of ViewHolders. It has support for a click listener that will be added to the whole row via onClick() and also for more complex bindings via onBind()

You can take a look at TestFragment for an example.

At this point you may be wondering:

If I have to move the adapter declaration to its own file, what is the benefit of the DSL?

I would argue that having a standardize way to define adapters is a plus on its own. I would also argue that the DSL has more value for simpler adapter types (i.e adapters with one row type and a single click listener) since it greatly reduces the number of classes created when compared to a regular adapter implementation.

What about testing?

Since BindableViewHolder and ModelAdaper take care of Viewholder binding and creation (and they are tested), the consumer is only responsible for testing that data is displayed and click listeners have the desired behavior. Both of these can be tested via Robolectric and/or Espresso at the Fragment/Activity level:

Note: For a more real life testing example take a look at ComicsFragmentTest

How do I add Adapt to my project?

  1. Make sure your project uses Data binding
  2. Add implementation me.emmano:adapt:0.2.0 to your build.gradle

That is it! I am really interested to see if others find this library useful, and how you would improve it, so please leave your comments below!

--

--