RecyclerView
RecyclerView is a modern and powerful replacement for older list components like ListView and GridView in Android.
It is designed for better performance, flexible layouts, and efficient memory usage when working with large or dynamic datasets.
Main Advantages
- Efficient view recycling using the
ViewHolderpattern. - Supports multiple layout styles (list, grid, staggered) via
LayoutManagers. - Offers built-in support for animations using
ItemAnimator. - Clean separation of data handling and UI rendering through the use of an
Adapter. - Improved performance compared to
ListViewby reusing views rather than inflating new ones each time.
Common LayoutManagers
- LinearLayoutManager: Displays items in a vertical or horizontal list.
- GridLayoutManager: Displays items in a grid (rows and columns).
- StaggeredGridLayoutManager: Allows uneven (masonry-style) grids.
Implementation Steps
- Add RecyclerView dependency in
build.gradle (Module):implementation "androidx.recyclerview:recyclerview:1.3.1" - Add RecyclerView to XML layout:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> - Create layout file for individual items (e.g.
item_view.xml):<TextView android:id="@+id/itemText" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" android:textSize="20sp" /> - Create a ViewHolder class:
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val textView: TextView = itemView.findViewById(R.id.itemText) }The
ViewHolderclass holds references to the views inside each item layout so they can be reused without repeatedly callingfindViewById(). - Create an Adapter class:
class MyAdapter(private val items: List<String>) : RecyclerView.Adapter<MyViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_view, parent, false) return MyViewHolder(view) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.textView.text = items[position] } override fun getItemCount(): Int = items.size }The
onCreateViewHolder()method inflates the layout XML only when needed and returns aViewHolder. TheonBindViewHolder()method is responsible for binding data to the views inside an existingViewHolder—it does not inflate or create new views. - Set up RecyclerView in your Activity:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val recyclerView = findViewById<RecyclerView>(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(this) val itemList = listOf("Item 1", "Item 2", "Item 3") val adapter = MyAdapter(itemList) recyclerView.adapter = adapter } }
How View Recycling Works
On scrolling through a RecyclerView, views that move off-screen are placed into a recycled view pool instead of being destroyed.
These views are reused for new items coming on-screen, which improves performance by avoiding repeated view creation and inflation.
The onCreateViewHolder() method is called only when a new view is needed and handles inflating the item layout and creating
a ViewHolder. Once the view is created, it can be reused.
The onBindViewHolder() method does not create or inflate views—it simply binds the appropriate data to the existing views
held by the ViewHolder. This separation between view creation and data binding allows RecyclerView to operate
efficiently, even with large datasets.
In short, the ViewHolder holds references to views, onCreateViewHolder() inflates and prepares them, and
onBindViewHolder() fills them with data as needed. This coordinated reuse mechanism is what gives RecyclerView its name and efficiency.
Alternative of RecyclerView in Jetpack Compose
In Jetpack Compose, the equivalent of RecyclerView is LazyColumn for vertical lists and LazyRow for horizontal ones.
Compose lists often require less boilerplate and are easier to write and read. These composables display only the visible items on screen and load more as
the user scrolls—this behavior is known as lazy loading. LazyColumn doesn't reuse or recycle view objects. Instead, it
recomposes list items on demand based on the current scroll position and visible viewport. It differs from RecyclerView, which
recycles a limited number of view objects and reuses them as they scroll off-screen to show new data.
The lazy composition approach for LazyColumn and LazyRow in Jetpack Compose aligns with its declarative model,
where the UI is redrawn based on changes in state. Recomposition may seem less efficient in theory, but Compose is optimized to make it lightweight and fast.
RecyclerView may still be preferable in some Compose-based apps—particularly when dealing with advanced features such as
custom touch gestures, drag-and-drop support, nested scrolling, complex item decorations, or animation behaviors that are mature and well-tested in the View system.
When needed, RecyclerView can be embedded in Compose layouts using AndroidView.
LazyColumn is the recommended choice for most new apps written in Jetpack Compose due to its simplicity and native integration.
However, for feature-rich, highly customized lists or integration with existing View-based code, RecyclerView remains a powerful and proven option.