
Differences & Uses Of @Immutable vs @Stable in Jetpack Compose
When building modern UI with Jetpack Compose, understanding the nuances between @Immutable and @Stable annotations can significantly affect your app’s performance and stability. While both annotations serve different purposes, they work together to help Compose efficiently manage recompositions.
Table of Contents
What is @Immutable?
The @Immutable annotation marks objects whose properties cannot be modified after initialization, ensuring that the object’s state remains unchanged. However, this does not guarantee that the object’s state will remain constant throughout the lifetime of the application, but rather that the object itself is immutable and its methods are referentially transparent. This is particularly useful for data classes or objects that don’t hold any mutable state.
data class Profile(
val name: String,
val age: Int
)In this example, the Profile class is immutable, meaning Compose can skip recompositions when the object itself doesn’t change. However, Compose still observes changes in the UI tree and determines whether a recompose is needed based on whether the Profile object itself is updated.
When to Use @Immutable?
You should use @Immutable when dealing with data that remains constant, such as user details, configuration settings, or any static data that won’t change after initialization. By marking these objects as immutable, you allow Compose to optimize its rendering and avoid redundant recompositions.
Learn more about managing immutability in data classes on Google’s Kotlin Style Guide.
What is @Stable?
The @Stable annotation marks objects that can change internally, but Compose is aware of these changes. When a property of a @Stable object changes, Compose will recompose the affected UI elements accordingly, ensuring that only necessary recompositions are triggered.
@Stable
class UserSettings {
var theme: MutableState<String> = mutableStateOf("Light")
private set
fun changeTheme(newTheme: String) {
theme.value = newTheme
}
}In this example, the UserSettings class can change its internal theme property, and if this change affects the UI, Compose will recompose the affected parts of the UI. Compose will only recompose where necessary, but it will still observe changes to mutable properties within @Stable objects. This ensures efficient rendering while maintaining flexibility in the object’s internal state.
When to Use @Stable?
Use @Stable for objects that may change internally, and Compose will monitor those changes. If changes affect the UI, Compose will trigger recompositions where necessary. This ensures efficient updates without unnecessary recompositions, even when the object’s internal state is mutable., such as preferences, settings, or internal component states. It helps Compose determine when an object has been updated in a meaningful way.
Explore the power of stable state management in Compose on Jetpack Compose State Documentation.
Best Practices for @Immutable and @Stable
Choosing between @Immutable and @Stable boils down to how your objects are structured and how you intend them to behave in your UI:
Use @Immutable for truly static data that never changes after it’s created.
Use @Stable for objects that may change internally, but not in a way that affects the UI’s rendering efficiency.
By applying these annotations correctly, you can drastically reduce unnecessary recompositions in Compose, leading to a smoother and more performant UI.
Examples in Action
Here’s a quick example to see how @Immutable and @Stable work together to optimize UI performance in Jetpack Compose:
@Composable
fun UserProfile(profile: Profile) {
Text(text = "Name: ${profile.name}")
Text(text = "Age: ${profile.age}")
}
@Composable
fun SettingsScreen(userSettings: UserSettings) {
Button(onClick = { userSettings.changeTheme("Dark") }) {
Text("Change Theme")
}
}In this example, the UserProfile composable will not recompose unless the Profile object itself changes (since it is marked with @Immutable), while the SettingsScreen composable can recompose when the changeTheme method is called in UserSettings, which is marked as @Stable.
Conclusion
Understanding and properly using @Immutable and @Stable annotations is crucial for optimizing performance in Jetpack Compose applications. By leveraging these annotations, you can ensure that your app runs smoothly and avoids unnecessary UI updates.
For more in-depth guidance, check out the Compose Performance Documentation.
Did you like this article? You can subscribe to the newsletter to hear about new articles.
Related Posts
Görkem Kara
Görkem KARA is a Senior Android Developer with 9 years of experience. It produces innovative mobile solutions with technologies such as Kotlin, Java and Android SDK. He works as a freelancer and provides customized services on performance optimization, user experience design and application architecture in projects.







