Create dynamic lists with RecyclerView Part of Android Jetpack.
RecyclerView makes it easy to efficiently display large sets of data. You supply the data and define how each item looks, and the RecyclerView library dynamically creates the elements when they're needed.
As the name implies, RecyclerView recycles those individual elements. When an item scrolls off the screen, RecyclerView doesn't destroy its view. Instead, RecyclerView reuses the view for new items that have scrolled onscreen. RecyclerView improves performance and your app's responsiveness, and it reduces power consumption.
Several classes work together to build your dynamic list.
RecyclerView
is the ViewGroup
that contains the views
corresponding to your data. It's a view itself, so you add RecyclerView
to your layout the way you would add any other UI element.
Each individual element in the list is defined by a view holder object. When
the view holder is created, it doesn't have any data associated with it. After
the view holder is created, the RecyclerView
binds it to its data. You
define the view holder by extending
RecyclerView.ViewHolder
.
The RecyclerView
requests views, and binds the views to their data,
by calling methods in the adapter. You define the adapter by extending
RecyclerView.Adapter
.
The layout manager arranges the individual elements in your list. You can
use one of the layout managers provided by the RecyclerView library, or you can
define your own. Layout managers are all based on the library's
LayoutManager
abstract class.
You can see how all the pieces fit together in the RecyclerView sample app (Kotlin) or RecyclerView sample app (Java).
If you're going to use RecyclerView, there are a few things you need to do. They are explained in detail in the following sections.
Decide how the list or grid looks. Ordinarily, you can use one of the RecyclerView library's standard layout managers.
Design how each element in the list looks and behaves. Based
on this design, extend the ViewHolder
class. Your version of ViewHolder
provides all the functionality for your list items. Your view holder is a
wrapper around a View
, and that view is managed by RecyclerView
.
Define the Adapter
that associates your data with the ViewHolder
views.
There are also advanced customization options that let you tailor your RecyclerView to your exact needs.
The items in your RecyclerView are arranged by a
LayoutManager
class. The RecyclerView library provides three layout managers, which handle the
most common layout situations:
LinearLayoutManager
arranges the items in a one-dimensional list.GridLayoutManager
arranges the items in a two-dimensional grid:
GridLayoutManager
tries to make all
the elements in each row have the same width and height, but different rows
can have different heights.GridLayoutManager
tries to make all
the elements in each column have the same width and height, but different
columns can have different widths.StaggeredGridLayoutManager
is similar to GridLayoutManager
, but it does not require that items in a
row have the same height (for vertical grids) or items in the same column
have the same width (for horizontal grids). The result is that the items
in a row or column can end up offset from each other.You also need to design the layout of the individual items. You need this layout when you design the view holder, as described in the next section.
Once you determine your layout, you need to implement your Adapter
and
ViewHolder
. These two classes work together to define how your data is
displayed. The ViewHolder
is a wrapper around a View
that contains the
layout for an individual item in the list. The Adapter
creates ViewHolder
objects as needed and also sets the data for those views. The process of
associating views to their data is called binding.
When you define your adapter, you override three key methods:
onCreateViewHolder()
:
RecyclerView
calls this method whenever it
needs to create a new ViewHolder
. The method creates and initializes the
ViewHolder
and its associated View
, but does not fill in the view's
contents—the ViewHolder
has not yet been bound to specific data.
onBindViewHolder()
:
RecyclerView
calls this method to associate a ViewHolder
with data. The
method fetches the appropriate data and uses the data to fill in the view
holder's layout. For example, if the RecyclerView
displays a list of names,
the method might find the appropriate name in the list and fill in the view
holder's TextView
widget.
getItemCount()
:
RecyclerView
calls this method to get the size of the dataset. For example,
in an address book app, this might be the total number of addresses.
RecyclerView uses this to determine when there are no more items that can be
displayed.
Here's a typical example of a simple adapter with a nested ViewHolder
that
displays a list of data. In this case, the RecyclerView displays a simple list
of text elements. The adapter is passed an array of strings containing the text
for the ViewHolder
elements.
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
The layout for the each view item is defined in an XML layout file, as usual.
In this case, the app has a text_row_item.xml
file like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
A simple RecyclerView
implementation like this may be all you need. However,
the library also offers many ways to customize your implementation. For more
information, see Advanced RecyclerView
customization.
For more information about testing on Android, consult the following resources.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2023-06-02 UTC.