LazyColumn vs Column in Jetpack Compose: When to Switch for Smooth Lists
Performance differences between LazyColumn and Column, a minimal implementation example, and practical verification steps for Android UI lists.
19 Sept 2025, 21:47 UTC

Scrolling a list of five thousand items used to freeze my Compose UI. The root cause was a traditional Column that recomposed every element on every layout pass, forcing the framework to measure and place each item regardless of visibility.
The Column performance bottleneck
In Jetpack Compose, recombination is the process of re-evaluating composable functions when their state changes. A Column evaluates every child composable during each recomposition, which means a list of thousands of items triggers thousands of layout passes. Even if items are off-screen, they still contribute to the measurement phase, causing UI jank on low-end devices.
How LazyColumn virtualizes lists
LazyColumn is a vertically scrolling list that implements lazy virtualization. Instead of composing all items, it composes only the visible subset and recycles composition slots as the user scrolls. The component internally calculates the visible range, requests layout for just those items, and re-uses the same composition slots for new items that scroll into view. This keeps memory usage low and scroll performance smooth, even with 10000+ entries.
Minimal LazyColumn example
@Composable
fun UserList(items: List) {
LazyColumn(
contentPadding = PaddingValues(16.dp),
verticalScroll = rememberScrollState()
) {
items(items) { user ->
Text(text = user, style = MaterialTheme.typography.body1)
}
}
}
To add LazyColumn to a project, open Android Studio and ensure the following dependency is present in the build.gradle file:
implementation 'androidx.compose.ui:ui:2024.10.00'
Where to run: Android Studio > Gradle sync window (or run ./gradlew :app:syncGradle from the terminal). This requires a debug-build capable device or emulator running Android 10 (API 29) or newer, as LazyColumn is part of the Compose UI library.
Expected checks: Open the Layout Inspector, select the LazyColumn instance, and verify that the composed items count reflects only the visible range (typically 10-20 items for a phone screen). Smooth scrolling should be apparent on a mid-range device.
Relevant risk: If list items contain mutable state defined with remember { mutableStateOf(...) } without rememberSaveable, rotating the device may reset that state because LazyColumn does not preserve off-screen item state by default.
Trade-offs and limitations
- Small lists: For fewer than a hundred items, the overhead of lazy layout calculation can make LazyColumn slightly slower than a plain Column.
- State restoration: Across configuration changes, items that rely on local remember state need rememberSaveable or explicit keys to survive rotation.
- Compatibility: LazyColumn requires Compose 1.4+; older SDKs will not compile the API.
If your dataset exceeds a few hundred items and smooth scrolling is a priority, replace the Column with LazyColumn. For tiny lists, stick with Column to avoid unnecessary complexity. Verify the benefit by running the app on a device, opening the Layout Inspector, and confirming that only visible items appear in the composition tree. If state loss occurs after rotation, wrap the item’s state with rememberSaveable or provide a stable key to items(key = ...).
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.