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:
- Add the support library
Add RecyclerView AndroidX library dependency in your app/build.gradle.dependencies { ... implementation 'androidx.recyclerview:recyclerview:1.0.0' }
- Add the RecyclerView in the layout XML file
Add the RecyclerView inside the desired activity layout XML file inres/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>
- 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; } }
- Create a custom row layout
The row layout represents the layout of each single element displayed in the RecyclerView. Create a file inres/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>
- 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 methodsonCreateViewHolder()
inflates the row layout and initializes the View Holder.onBindViewHolder()
uses the View Holder constructed in theonCreateViewHolder()
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(); } }
- 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); } }
- 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)); } }