Combine your lists with MergeAdapter
Say bye-bye to view types 👋

Dynamic list-based UI is all the new rage. You know what it means — ViewTypes
! One for each type of view. Its all bells and whistles when working on a small project, but what about a production app with a dozen services and item animations? In these cases, managing multiple view types for a RecyclerView
can quickly get out of hands. So complex that Airbnb even built an entire architecture for this use-case.
However, there still lies a grey-area, where your app is not that small, neither too-big. Or probably you just don’t want to rely on a different architecture altogether. Luckily, Android developers thought of this.
Here comes MergeAdapter
With the latest release of RecyclerView
— recyclerview:1.2.0-alpha02
, there is a new class available named MergeAdapter
. It enables sequential merging of multiple adapters, before setting it to a single RecyclerView
. This eases the pain of showing different layouts together, without the need of maintaining any view types. All the logic related to different types of layout can be kept separate in different adapters, thereby helping us to keep our code and logic well organized and encapsulated.
Let’s see it in action:
As you can see, we first created two adapter individually, then we added them both to an instance of MergeAdapter
, and then finally passed this instance to the RecyclerView
.
Kind of reminds me of MediatorLiveData 🤷♂️
The result which can be obtained from these few lines of code? Here you go:

Isn’t it amazing!
If you think about it, this can be helpful in many cases. From having a header and footer maintained separately, to showing loaders and other unique layouts in a sequential manner, all without bloating the adapter responsible for showing the actual data in between.
Note that, this merge is sequential. Which essentially means when list of one type ends, after that only list of another type can be shown.
Minor details
If you have had a good-enough experience with RecyclerView, I know this “merging-adapter thingy” would only raise-more concerns for you, which may include but not limited to :
- And what about updating data with this adapter?
- What happens to
ViewHolder
? - Does it changes the way we get position of a list item?
- Will we get overall position or list-wise position?
Let’s try to find answers! 🧐
Updating list items
Since multiple adapters merge to form a merged adapter, issuing notify calls on any of the constituent adapters will trigger computation by the MergeAdapter
as well, which will then finally dispatch required updates to the RecyclerView
. It is recommended to dispatch updates in a more confined manner, rather than using notifyDataSetChanged
, which will trigger reloading of entire content of the RecyclerView
.
MergeAdapter
won’t map notifyDataSetChanged
to any other notify
calls.
ViewHolders
Each adapter will work with its own pool of ViewHolders
. Which means, if you combine multiple lists, their ViewHolders
will not spill over to the adjacent adapters. However, there may be case when adjacent adapters inflate the exact same layout for their list items, in which case it will be efficient to let them share their pool of ViewHolders
. To enable this, we need to pass in a MergeAdapter.Config
object with isolateViewTypes = false
, while constructing the MergeAdapter
.
While in the previous example, we saw the construction of MergeAdapter
, and the following adapter addition as:
val mergedAdapter = MergeAdapter() mergedAdapter.addAdapter(firstAdapter) mergedAdapter.addAdapter(secondAdapter)
to include a configuration, this will change to:
val configBuilder = MergeAdapter.Config.Builder()
configBuilder.setIsolateViewTypes(false)val config = configBuilder.build()
val mergedAdapter = MergeAdapter(config,firstAdapter,secondAdapter)
Using MergeAdapter.Config
, we can also change the stableIdMode
to one of NO_STABLE_IDS
, ISOLATED_STABLE_IDS
and SHARED_STABLE_IDS
. For more info on stableIdMode
check out this link.
Getting ViewHolder positions
In a simple adapter we use ViewHolder.getAdapterPosition()
to get the position of the current list item. Since MergeAdapter
combines various adapters, to achieve the same use ViewHolder.getBindingAdapterPosition()
. But keep in mind, that this will return the position with respect to the adapter it is in, and not the whole MergeAdapter
.

To get the position with respect to the MergeAdapter
, use ViewHolder.getAbsoluteAdapterPosition()
instead.
For a complete implementation, have a look at the code in my sample project on MergeAdapter
(of which these screenshots are) on Github :
This ends our hands-on with the wonderful new MergeAdapter
.
Clap if you too feel thankful to Android developers for giving us this awesome piece of code! 👏