

Display Objects of Different Types in a RecyclerView
So, you may be trying to set up a RecyclerView that has different ViewHolders. For instance, a Post object that could have a picture or might be just text with different ViewHolders for each case.
While the code in the guide covers that scenario, we are going to take it a step further and also tackle a slightly different problem. Our goal is to add objects of different types to a single RecyclerView in a simple to implement and easy to manage way.
The Problem:
We have three objects: Book, Magazine, and Newspaper. We want to display them in one feed by hooking up a single List to a RecyclerView.Adapter. We also want each object type to look different in the RecyclerView.
What We’ll Need:
- An interface that
Book,Magazine, andNewspaperwill implement - A
RecyclerView.Adapterwith aListof interfaces that can be cast into different types - A
ViewHolderandlayoutfor each object type
The Interface
Let’s start by creating a Literature interface that all our objects will implement. In the interface we will add a getType() method and some constants that represent the different types. i.e. TYPE_MAGAZINE.
public interface Literature {
int TYPE_BOOK = 101;
int TYPE_MAGAZINE = 102;
int TYPE_NEWSPAPER = 103;
int getType();
}Now, in each of our objects, let’s implement the Literature interface, override the getType() method, and return the correct type for that object.
The RecyclerView.Adapter
First, let’s add our List of Literatures as a member variable in the Adapter.
public class LiteratureAdapter extends RecyclerView.Adapter {
private List<Literature> mLiteratureList;
}We will also need three ViewHolders as inner classes in the Adapter. One for each object type.
We’ll need to override four methods in the RecyclerView.Adapter. The first of which is getItemViewType(). This will look at an item in mLiteratureList and determine if it’s a Book, Magazine, or Newspaper then pass that result to onCreateViewHolder() (which we will implement next).
@Override
public int getItemViewType(int position) {
return mLiteratureList.get(position).getType();
}
In onCreateViewHolder() we’ll create a new ViewHolder depending on the type sent from getItemViewType(). Note: In most use cases, you will also have to create a separate layout resource for each ViewHolder .
In onBindViewHolder() call getItemViewType() manually. Depending on the type that it returns, cast the generic ViewHolder parameter to the appropriate type and call its bindView() method.
The code in getItemCount() is going to look the same as in your standard RecyclerView.Adapter.
@Override
public int getItemCount() {
if (mLiteratureList == null) {
return 0;
} else {
return mLiteratureList.size();
}
}
Setting the data
The following setter is possible, but NOT recommended.
public void setLiteratureList(List<Literature> literatureList) {
mLiteratureList = literatureList;
notifyDataSetChanged();
}The problem with this approach is either:
a. In other parts of your app you will have to deal with Literature objects. Which means you will constantly have to check the type and cast them appropriately to get at the data and methods.
or
b. You will need to cast your List to a List<Literature> before you can use the setter.
Another option is to accept any class that implements our Literature interface, then replace the contents of mLiteratureList.
public void setLiteratureList(List<? extends Literature> literatureList) {
if (mLiteratureList == null){
mLiteratureList = new ArrayList<>();
}
mLiteratureList.clear();
mLiteratureList.addAll(literatureList);
notifyDataSetChanged();
}By following this method, you are able to use a List of Books, Magazines, or Newspapers as the parameter.
And that’s going to do it. Enjoy your new RecyclerView.Adapter and don’t hesitate to reach out if you have any questions.
Check out the full RecyclerView.Adapter code here.