Introduction

RecyclerView is a ViewGroup that renders any adapter-based view in a similar way. RecyclerView is a more flexible pattern of view recycling than ListView and GridView. RecyclerView focuses only on recycling views. All the other actions needed to create a view, like how to present data set or inflate the views are delegated to the pluggable classes and that is what makes it so flexible.

 

Components

RecyclerView has below main componet

  • Layout Managers : A layout manager positions item views inside a RecyclerView and determines when to reuse item views that are no longer visible to the user.
  • RecyclerView.Adapter : Supplies data to view holder.
  • ItemAnimator : It will animate ViewGroup modifications such as add/delete/select that are notified to the adapter.

 

Comparision

RecyclerView differs from its predecessor ListView primarily because of the following features:

  • ListView adapters do not require the use of the ViewHolder pattern while RecyclerView requires the use of the ViewHolder pattern for which it uses RecyclerView.Viewholder.
  • ListView can only layout items in a vertical linear arrangement and this cannot be customized. In contrast, the RecyclerView has a RecyclerView.LayoutManager that allows any item layouts including horizontal lists or staggered grids.
  • ListView contains no special provisions through which one can animate the addition or deletion of items. In contrast, the RecyclerView has the RecyclerView.ItemAnimator class for handling item animations.
  • ListView had adapters for different sources such as ArrayAdapter and CursorAdapter for arrays and database results respectively. In contrast, the RecyclerView.Adapter requires a custom implementation to supply the data to the adapter.
  • ListView has a AdapterView.OnItemClickListener interface for binding to the click events for individual items in the list. In contrast, RecyclerView only has support for RecyclerView.OnItemTouchListener which manages individual touch events but has no built-in click handling.

 

Using RecyclerView

To use the RecyclerView you need to follow the following steps:

  1. Add the support library
    Add RecyclerView AndroidX library dependency in your app/build.gradle.

    dependencies {
        ...
        implementation 'androidx.recyclerview:recyclerview:1.0.0'
    }
  2. Add the RecyclerView in the layout XML file
    Add the RecyclerView inside the desired activity layout XML file in res/layout/

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    
      <androidx.recyclerview.widget.RecyclerView
          android:id="@+id/rvContacts"
          android:layout_width="0dp"
          android:layout_height="0dp"
          app:layout_constraintBottom_toBottomOf="parent"
          app:layout_constraintEnd_toEndOf="parent"
          app:layout_constraintStart_toStartOf="parent"
          app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
  3. Defining a Model
    Every RecyclerView is backed by a source for data. We need a class that represents a single RecyclerView item data, create a file named Data.java.

    public class Contact {
      private String mName;
      private boolean mOnline;
    
      public Contact(String name, boolean online) {
        mName = name;
        mOnline = online;
      }
    
      public String getName() {
        return mName;
      }
    
      public boolean isOnline() {
        return mOnline;
      }
    
      private static int lastContactId = 0;
    
      public static ArrayList<Contact> createContactsList(int numContacts) {
        ArrayList<Contact> contacts = new ArrayList<Contact>();
    
        for (int i = 1; i <= numContacts; i++) {
            contacts.add(new Contact("Person " + ++lastContactId, i <= numContacts / 2));
        }
    
        return contacts;
      }
    }
  4. Create a custom row layout
    The row layout represents the layout of each single element displayed in the RecyclerView. Create a file in res/layout/

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="10dp"
        android:paddingBottom="10dp">
    
      <TextView
        android:id="@+id/contact_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
    
      <Button
        android:id="@+id/message_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textSize="10sp"/>
    </LinearLayout>
  5. Create the  RecyclerView.Adapter to populate data into the RecyclerView
    RecyclerView.Adapter requires a custom implementation to supply data to the adapter. The adapter has below methods

    • onCreateViewHolder() inflates the row layout and initializes the View Holder.
    • onBindViewHolder() uses the View Holder constructed in the onCreateViewHolder() method to populate the current row of the RecyclerView with data.
    • getItemCount () determine the number of items.

     

    public class ContactsAdapter extends
       RecyclerView.Adapter<ViewHolder> {
    
      // Constructor and member variables
    
      // Inflate a layout from XML and return the view holder
      @Override
      public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
    
        // Inflate the custom layout
        View contactView = inflater.inflate(R.layout.item_contact, parent, false);
    
        // Return a new holder instance
        ViewHolder viewHolder = new ViewHolder(contactView);
        return viewHolder;
      }
    
      // Populate data into the item through holder
      @Override
      public void onBindViewHolder(ViewHolder viewHolder, int position) {
    
        // Get the data model based on position
        Contact contact = mContacts.get(position);
    
        // Set item views based on your views and data model
        TextView textView = viewHolder.nameTextView;
        textView.setText(contact.getName());
        Button button = viewHolder.messageButton;
        button.setText(contact.isOnline() ? "Message" : "Offline");
        button.setEnabled(contact.isOnline());
      }
    
      // Returns the total count of items in the list
      @Override
      public int getItemCount() {
          return mContacts.size();
      }
    }
  6. Create the ViewHolder to provide a reference to the views for each data item
    The RecyclerView uses a ViewHolder to store the references to the relevant views for one entry in the RecyclerView.

    public class ViewHolder extends RecyclerView.ViewHolder {
    
      public TextView nameTextView;
      public Button messageButton;
    
      public ViewHolder(View itemView) {
          // Stores the itemView in a public final member variable that can be used
          // to access the context from any ViewHolder instance.
          super(itemView);
    
          nameTextView = (TextView) itemView.findViewById(R.id.contact_name);
          messageButton = (Button) itemView.findViewById(R.id.message_button);
      }
    }
  7. Bind the Adapter to the RecyclerView in the Activity
    In our activity, we will populate a set of sample users which should be displayed in the RecyclerView.

    public class UserListActivity extends AppCompatActivity {
    
      ArrayList<Contact> contacts;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
    
        // Lookup the recyclerview in activity layout
        RecyclerView rvContacts = (RecyclerView) findViewById(R.id.rvContacts);
    
        // Initialize contacts
        contacts = Contact.createContactsList(20);
        // Create adapter passing in the sample user data
        ContactsAdapter adapter = new ContactsAdapter(contacts);
        // Attach the adapter to the recyclerview to populate items
        rvContacts.setAdapter(adapter);
        // Set layout manager to position the items
        rvContacts.setLayoutManager(new LinearLayoutManager(this));
      }
    }