Interview QuestionPractical QuestionFollow-up Questions

mutableStateListOf and mutableStateMapOf in Jetpack Compose

skydovesJaewoong Eum (skydoves)||6 min read

mutableStateListOf and mutableStateMapOf in Jetpack Compose

Jetpack Compose provides mutableStateListOf and mutableStateMapOf as observable collection types that integrate with the snapshot state system. Unlike regular MutableList or MutableMap, modifications to these collections are tracked by Compose and automatically trigger recomposition for any composable that reads them. Understanding how these collections work under the hood and when to use them over alternatives like mutableStateOf(list) is a common topic in Compose interviews. By the end of this lesson, you will be able to:

  • Explain how mutableStateListOf and mutableStateMapOf integrate with the snapshot system.
  • Distinguish between mutableStateListOf and mutableStateOf(mutableListOf()) in terms of granularity.
  • Apply observable collections correctly with remember to build reactive UIs.
  • Identify common mistakes that break observation or cause unexpected recompositions.

How Observable Collections Work

mutableStateListOf returns a SnapshotStateList, which implements MutableList and participates in Compose's snapshot system. Every structural mutation (add, remove, set, clear) writes to the snapshot, and every read (get, iterate, size) creates a dependency. Compose tracks these reads and invalidates the composition when a mutation occurs:

@Composable
fun TaskList() {
    val tasks = remember { mutableStateListOf("Setup", "Build", "Deploy") }

    Column {
        tasks.forEach { task ->
            Text(text = task)
        }
        Button(onClick = { tasks.add("Test") }) {
            Text("Add Task")
        }
    }
}

When the button is clicked, tasks.add("Test") mutates the SnapshotStateList. Compose detects that the forEach loop reads from this list and schedules recomposition for TaskList. The new item appears without any manual notification.

mutableStateMapOf works identically but for key value pairs, returning a SnapshotStateMap that implements MutableMap:

@Composable
fun PreferencesScreen() {
    val prefs = remember {
        mutableStateMapOf("notifications" to true, "darkMode" to false)
    }

    Column {
        prefs.forEach { (key, value) ->
            Row {
                Text(text = key)
                Switch(
                    checked = value,
                    onCheckedChange = { prefs[key] = it }
                )
            }
        }
    }
}

This interview continues for subscribers

Subscribe to Dove Letter for full access to exclusive interviews about Android and Kotlin development.

Become a Sponsor