1. 程式人生 > >Display Objects of Different Types in a RecyclerView

Display Objects of Different Types in a RecyclerView

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).

@Overridepublic 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.

@Overridepublic int getItemCount() {    if (mLiteratureList == null) {        return 0;    } else {        return mLiteratureList.size();    }}

Setting the data

The following setter is possible, butNOT recommended.

public void setLiteratureList(List<Literature> literatureList) {    mLiteratureList = literatureList;    notifyDataSetChanged();}

The problem with this approach is either:

a. In other parts of you 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.