Kotlin RecyclerView Basics
RecyclerView is the standard Android widget for displaying long, scrollable lists efficiently. It recycles item views as you scroll — instead of creating a new view for every item, it reuses off-screen views with new data. This keeps large lists smooth and memory-efficient.
Why RecyclerView Instead of ListView
ListView (old):
Creates a new view for each item as you scroll
Slow and memory-heavy for large datasets
No built-in animation or layout flexibility
RecyclerView (modern):
Recycles views — reuses off-screen views with new data
Works with any layout (vertical, horizontal, grid)
Built-in item animations
Required adapter pattern enforces good architecture
How RecyclerView Works
┌─────────────────────────────────────────────────────┐
│ RecyclerView │
│ │
│ ┌─────────────┐ ← visible items on screen │
│ │ Item View │ │
│ ├─────────────┤ │
│ │ Item View │ │
│ ├─────────────┤ │
│ │ Item View │ │
│ └─────────────┘ │
│ │
│ LayoutManager → arranges items (Linear/Grid) │
│ Adapter → provides data for each position │
│ ViewHolder → holds references to item views │
└─────────────────────────────────────────────────────┘
When an item scrolls off screen:
ViewHolder is put in a "recycle pool"
New data is bound to the recycled ViewHolder
→ No new views created → smooth and fast
Step 1: Add Dependency
// In app/build.gradle.kts:
dependencies {
implementation("androidx.recyclerview:recyclerview:1.3.2")
}Step 2: Create Item Layout (res/layout/item_product.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<TextView
android:id="@+id/productName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp" />
<TextView
android:id="@+id/productPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>Step 3: Create the Adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
data class Product(val name: String, val price: Double)
class ProductAdapter(
private val products: List,
private val onItemClick: (Product) -> Unit
) : RecyclerView.Adapter() {
// ViewHolder: stores references to the views inside one item row
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameText: TextView = itemView.findViewById(R.id.productName)
val priceText: TextView = itemView.findViewById(R.id.productPrice)
}
// Called when RecyclerView needs a new ViewHolder (new cell)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_product, parent, false)
return ViewHolder(view)
}
// Called to bind data to a recycled or new ViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val product = products[position]
holder.nameText.text = product.name
holder.priceText.text = "₹${product.price}"
holder.itemView.setOnClickListener { onItemClick(product) }
}
// Total number of items in the list
override fun getItemCount() = products.size
} Step 4: Set Up RecyclerView in Activity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class ProductListActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_product_list)
val products = listOf(
Product("Laptop", 75000.0),
Product("Mouse", 800.0),
Product("Keyboard", 1500.0),
Product("Monitor", 18000.0),
Product("Webcam", 3000.0)
)
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
// LinearLayoutManager = vertical scrolling list
recyclerView.layoutManager = LinearLayoutManager(this)
// Set the adapter with a click handler
recyclerView.adapter = ProductAdapter(products) { product ->
Toast.makeText(this, "Selected: ${product.name}", Toast.LENGTH_SHORT).show()
}
}
}Activity Layout (activity_product_list.xml)
<RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />Layout Manager Options
// Vertical list (default)
LinearLayoutManager(this)
// Horizontal scrolling list
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
// 2-column grid
GridLayoutManager(this, 2)
// Staggered grid (Pinterest-style)
StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)Updating the List Efficiently
// After data changes, tell the adapter what changed:
adapter.notifyItemInserted(products.size - 1) // one item added at end
adapter.notifyItemRemoved(position) // one item removed
adapter.notifyItemChanged(position) // one item updated
adapter.notifyDataSetChanged() // entire list changed (avoid if possible)
// Best practice: use DiffUtil or ListAdapter for automatic diffing