Back to Blog
Jetpack Compose

Column vs LazyColumn in Jetpack Compose

June 2025 • 7 min read

In Jetpack Compose, choosing between a standard Column and a LazyColumn is one of the most common architectural decisions developers make. While both arrange UI elements vertically, the way they handle memory and rendering is fundamentally different.

1. The Core Difference: Eager vs Lazy

The most important distinction between Column and LazyColumn lies in when composables are created and drawn.

Standard Column

A Column is eager. When you place items inside it, Compose immediately measures and renders every single item — even those that are currently off-screen.

  • • Best for small, static content
  • • Ideal for profile pages, settings screens, and forms
  • • Does not scroll by default

To make a Column scrollable, you must explicitly add a scroll modifier.


        val scrollState = rememberScrollState()

        Column(
            modifier = Modifier.verticalScroll(scrollState)
        ) {
            itemsList.forEach { item ->
                Text("Item $item")
            }
        }
      

LazyColumn

A LazyColumn is lazy by design, similar to RecyclerView in the traditional View system. It only composes and lays out the items that are currently visible on screen.

  • • Best for large or dynamic datasets
  • • Built-in scrolling support
  • • Efficient memory usage

        LazyColumn {

            item {
                Text(
                    text = "Header Section",
                    style = MaterialTheme.typography.h4
                )
            }

            items(itemsList) { item ->
                MyListItem(item)
            }
        }
      

2. When Performance Matters

Using Column for large datasets can silently degrade performance. Since all items are composed eagerly, memory usage increases and recompositions become expensive.

If your list can grow beyond one screen, LazyColumn should be your default choice.

3. Pro Tips for LazyColumn

When using LazyColumn in production apps, there are two optimizations you should always apply.

Always Provide Keys

Keys allow Compose to identify which items changed, moved, or were removed — preventing unnecessary recompositions.


items(
    items = userList,
    key = { user -> user.id }
) { user ->
    UserRow(user)
}
      

Use contentType for Mixed Rows

If your list contains multiple item types (images, text, headers), providing contentType allows Compose to reuse layouts more efficiently.

Final Recommendation

The choice between Column and LazyColumn comes down to data size and behavior.

  • • Use Column for small, fixed UI that fits on one screen
  • • Use LazyColumn for lists backed by APIs, databases, or user-generated content

Choosing the right layout early prevents performance issues and keeps your Compose UI scalable as your app grows.

Select Theme