Snip3r_bow Snip3r_bow - 5 months ago 15
Android Question

How to proper display an ArrayList in a RecyclerView?

I need to add an

Activity
where I can list the elements of an
ArrayList<CustomClass>
and I've seen there's a newer and better way to display lists -
RecyclerView
.

My question is how to implement this into my app.
I've found that I need to use an
Adapter
, but I don't quite understand how to implement the whole process correctly.

If you're wondering, I'm referring to this examples of the docs, which I have been reading.

Answer

I remember when I was first reading about RecyclerViews - I agree it can be a little confusing at first.

1. Adding the RecyclerView

First you need to add your RecyclerView to your XML layout. I'm assuming you know how to do this. You also declare it in your Java code:

RecyclerView myList = (RecyclerView) findViewById(R.id.your_recycler_view);

2. Creating the Adapter and understanding ViewHolder

Next, you need to create an Adapter for it. This is a class that implements RecyclerView.Adapter<YourAdapter.YourViewHolder>. I will explain what this means in a minute.

I believe it helps to look at an example of an Adapter to understand how it works (e.g. one I created for an open-source app).

You can see that the Adapter class contains an inner class, which is your ViewHolder. Therefore, it needs to extend RecyclerView.ViewHolder.

Inside this ViewHolder, you declare the variables for the layouts that will be used for each list item in your RecyclerView. In the constructor for your ViewHolder, you assign these variables. I'm referring to this part of the code (I'm giving my example below):

  CoursesViewHolder(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        card = (CardView) itemView.findViewById(R.id.card);
        title = (TextView) itemView.findViewById(R.id.title);
        subtitle = (TextView) itemView.findViewById(R.id.subtitle);
    }

That's all you need for your ViewHolder (the inner class in your Adapter).

3. Understanding the Adapter

Like most Java objects, you will need to have a constructor some private variables in your Adapter class. Here are mine:

private Context mContext;
private ArrayList<Course> mArrayCourses;

public CoursesAdapter(Context context, ArrayList<Course> arrayCourses) {
    mContext = context;
    mArrayCourses = arrayCourses;
}

You will definitely need to have your ArrayList<CustomClass> as a constructor parameter and a private variable, but I have also included Context in my example.

If you look at the rest of the Adapter class, it contains some methods which it overrides from what it extends. Let's have a quick look at what these are:

  • getItemCount() returns the size of your list.
  • onCreateViewHolder(...) is used to inflate the layout for your list item.
  • onBindViewHolder(...) configures your layouts for the list item (e.g. setting text to a TextView)

For most cases, getItemCount() will just return the size() of your ArrayList<CustomClass>.

The onCreateViewHolder(...) method generally stays the same too. Here is mine:

@Override
public CoursesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_course, parent, false);
    return new CoursesViewHolder(view);
}

You can see that I am inflating the layout that I will use as my list item (card_course). Of course, your layout will be different, and the return type of this method will match whatever you named your ViewHolder inner class.

Now, the interesting bit is in onBindViewHolder(...). You configure your layouts here, so it is completely up to you what you want to do. Here's a template you could use:

@Override
public void onBindViewHolder(YourViewHolder holder, int position) {
    CustomClass object = mArrayCustom.get(position);

    holder.textView.setText(object.getName());
}

Basically, you access your ViewHolder variables (for the widgets in your list item layout) by doing holder.myWidget. The holder part is coming from the parameter, which is your ViewHolder we talked about earlier.

In the example above, the object has a getName() method, and the ViewHolder contains a textView, so I am setting the text.

There is also one more method - onAttachedToRecyclerView(...). You can use this for more complex things, but at a basic level, it is usually this:

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

4. Configuring RecyclerView

Remember at the beginning, when we declared and assigned our RecyclerView?:

RecyclerView myList = (RecyclerView) findViewById(R.id.your_recycler_view);

Now we are going to configure it.

You start by setting a "layout manager". This determines how each list item will be displayed on screen. The common ones are LinearLayoutManager and GridLayoutManager. The former puts your list items into a standard list (nothing special really, but it is very useful), and the latter organises your list items into a grid type of layout.

In our example, we're going to use a LinearLayoutManager. To set this on the RecyclerView, we do this:

myList.setLayoutManager(new LinearLayoutManager(this));

That's all.

And all we have to do next is to set the Adapter class we created and customised earlier to your RecyclerView:

YourAdapter adapter = new YourAdapter(yourCustomArrayList);
myList.setAdapter(adapter);

In the above, I'm assuming your adapter only has one parameter, but this will depend on how you configured it earlier.

5. Using your RecyclerView

The steps above should give you a working RecyclerView. If you get stuck, remember you can look at one of my examples here.

You can also look through the Google samples for the RecyclerView implementation.

I hope all of this gave you a clear idea about how RecyclerView works.