× Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This tutorial describes how to use the RecylerView widget in Android applications.

1. Android and list or grids

1.1. Using lists or grids in Android

The display of elements in a list or grids is a very common pattern in mobile applications. The user sees a collection of items and can scroll through them. The collection of items can be a list, a grid or another structured representations of data. Such an activity is depicted in the following picture.

Listview example

The user interacts with the collection of items via touch events or the toolbar. Individual items can be selected. This selection may update the toolbar or may trigger a detailed screen based on the selection. The following graphic sketches that.

Listview example

1.2. Using RecyclerView

The RecyclerView class supports the display of a collection of data.

It is a modernized version of the ListView and the GridView classes provided by the Android framework. Recycler view addresses several issues that the existing widgets have. It enforced a programming style that results in good performance. It also comes with default animations for removing and adding elements.

RecyclerView allow to use different layout managers for positioning items.

Recycler view uses a ViewHolder to store references to the views for one entry in the recycler view. A ViewHolder class is a static inner class in your adapter which holds references to the relevant views. With these references your code can avoid the time-consuming findViewById() method to update the widgets with new data.

1.3. Adapters

An adapter manages the data model and adapts it to the individual entries in the widget. It extends the RecyclerView.Adapter class and is assiged to the recycler view via the RecyclerView.setAdapter method. The input to the adapter of an recycler view can be any arbitrary Java objects. Based on this input the adapter must return the total number of items via its getItemCount() method.

The adapter prepares the layout of the items by inflating the correct layout for the individual data elements. This work is done in the onCreateViewHolder method. It returns an object of type ViewHolder per visual entry in the recycler view.

This instance is used to access the views in the inflated layout. The onCreateViewHolder method is only called then a new view must be created.

Every visible entry in a recycler view is filled with the correct data model item by the adapter. Once a data item becomes visible, the adapter assigns this data to the individual widgets which he inflated earlier. This work in done in the onBindViewHolder method.

For example, an entry in a list may have an image on the left side and two text lines in the middle as depicted in the following graphic.

Recycler view example layout

A layout file for a such a line might look like the following.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
        android:contentDescription="TODO"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/icon"
        android:ellipsize="marquee"
        android:singleLine="true"
        android:text="Description"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/firstLine"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/secondLine"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignWithParentIfMissing="true"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:text="Example application"
        android:textSize="16sp" />

</RelativeLayout>

1.4. Gradle dependency to use recycler view

The RecyclerView widget is delivered as library and can be used as of API 7 level or higher. Add the a dependency to the latest version of this library to your Gradle build file to use it.

dependencies {
    ...
    compile "com.android.support:recyclerview-v7:25.1.1"
}

1.5. Default layout manager

The layout manager decides how the data in the RecyclerView is displayed. The recycler view library provides the following build-in layout managers.

  • LinearLayoutManager shows items in a vertical or horizontal scrolling list.

  • GridLayoutManager shows items in a grid.

  • StaggeredGridLayoutManager shows items in a staggered grid.

1.6. Relevant implementation classes to use RecyclerView

The implementation of RecyclerView requires a few classes to be implemented. The most important classes are listed in the following table

Table 1. Important classes of the RecyclerView API
Class Purpose Optional

Adapter

Provides the data and responsible for creating the views for the individual entry

Required

ViewHolder

Contains references for all views that are filled by the data of the entry

Required

LayoutManager

Contains references for all views that are filled by the data of the entry

Required, but default implementations available

ItemDecoration

Responsible for drawing decorations around or on top of the view container of an entry

Default behavior, but can be overridden

ItemAnimator

Responsible to define the animation if entries are added, removed or reordered

Default behavior, but can be overridden

You can also provide your custom implementations for the layout managers and animations.

1.7. Handling click events in recycler view

Touch events, like clicking should be handled by the views in the recycler view. If the view should trigger something in the object in which it is used (activity or fragment), you can pass via the constructor of the adapter to it. This allows the adapter to store a reference to the object and call its methods for feedback.

1.8. Using different layouts in recycler view

The adapter needs to create a layout for each row of the list. This root of the layout is typically a ViewGroup (layout manager) and contains several other views, e.g., an ImageView and a TextView. The following graphic shows a list with different layouts for odd and even rows.

Adapter provides data and defines the layout per row

Within the getItemViewType method the recycler view determines which type should be used for data. The framework call automatically the onCreateViewHolder method if needed for this type. In this method you inflate the correct layout for the type and return a fitting view holder.

1.9. Custom animations

To customize the animations in the RecyclerView, implement your own animation by extending the RecyclerView.ItemAnimator class and use the RecyclerView.setItemAnimator() method to assign it to your widget.

1.10. Filtering and sorting

Filtering and sorting of the data is handled by the adapter. You need to implement the logic in your custom adapter implementation.

1.11. Data updates in the adapter

The notifyItemInserted(position) method on the adapter can be used to notify the view that a new entry has been inserted at a certain position.

The notifyItemRemoved(position); method can be used to notify the view that a entry has been deleted in a certain position.

2. Exercise: Using RecylerView in a new Android application

In this exercise you create a project which uses the RecyclerView class to display a list.

RecyclerView example

2.1. Create projects and add the Gradle dependency

Create a new Android project using the com.vogella.android.recylerview top level package name.

Add a required dependency to your Gradle build file. See Gradle dependency to use recycler view for details.

2.2. Create layout files

Create or update the a layout file called activity_main.xml so that it contains the RecyclerView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <!-- A RecyclerView with some commonly used attributes -->

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="12dp"
        android:layout_marginRight="12dp"
        android:elevation="2dp"
        android:src="@drawable/ic_add_circle" />

</RelativeLayout>

Note: The ImageView has the android:elevation attribute set, this instructs Android to draw a shadow for it.

Also create a layout to use in each item.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="6dip"
        android:contentDescription="TODO"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/secondLine"
        android:layout_width="fill_parent"
        android:layout_height="26dip"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/icon"
        android:ellipsize="marquee"
        android:singleLine="true"
        android:text="Description"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/firstLine"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/secondLine"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignWithParentIfMissing="true"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:text="Example application"
        android:textSize="16sp" />

</RelativeLayout>

Note: At the moment the display of the RecyclerView is not supported in the graphical preview.

Create the following adapter class.

package com.vogella.android.recyclerview;

import java.util.ArrayList;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
        private ArrayList<String> mDataset;

        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public class ViewHolder extends RecyclerView.ViewHolder {
                // each data item is just a string in this case
                public TextView txtHeader;
                public TextView txtFooter;

                public ViewHolder(View v) {
                        super(v);
                        txtHeader = (TextView) v.findViewById(R.id.firstLine);
                        txtFooter = (TextView) v.findViewById(R.id.secondLine);
                }
        }

        public void add(int position, String item) {
                mDataset.add(position, item);
                notifyItemInserted(position);
        }

        public void remove(String item) {
                int position = mDataset.indexOf(item);
                mDataset.remove(position);
                notifyItemRemoved(position);
        }

        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(ArrayList<String> myDataset) {
                mDataset = myDataset;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                        int viewType) {
                // create a new view
                View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout, parent, false);
                // set the view's size, margins, paddings and layout parameters
                ViewHolder vh = new ViewHolder(v);
                return vh;
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
                // - get element from your dataset at this position
                // - replace the contents of the view with that element
                final String name = mDataset.get(position);
                holder.txtHeader.setText(mDataset.get(position));
                holder.txtHeader.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                remove(name);
                        }
                    });

                holder.txtFooter.setText("Footer: " + mDataset.get(position));

        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
                return mDataset.size();
        }

}

Now you can configure your recyler view in your activity.

public class MyActivity extends Activity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);
    }
    ...
}

3. About this website

4. ListView Resources

4.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.