[ Web Proxy ]
URL:
Viewing: https://developer.android.com/develop/ui/compose/performance/stability [Back]  [Original]

Stability in Compose  |  Jetpack Compose  |  Android Developers Skip to main content
Essentials Design & Plan Develop Google Play Blog
Search:
Android Studio
Android Developers [Android Developers]

Stability in Compose Stay organized with collections Save and categorize content based on your preferences.

Compose considers types to be either stable or unstable. A type is stable if it is immutable, or if it is possible for Compose to know whether its value has changed between recompositions. A type is unstable if Compose can't know whether its value has changed between recompositions.

Compose uses the stability of a composable's parameters to determine whether it can skip the composable during recomposition:

If your app includes many unnecessarily unstable components that Compose always recomposes, you might observe performance issues and other problems.

This document details how you can increase the stability of your app to improve performance and overall user experience.

Immutable objects

The following snippets demonstrates the general principles behind stability and recomposition.

The Contact class is an immutable data class. This is because all its parameters are primitives defined with the val keyword. Once you create an instance of Contact, you cannot change the value of the object's properties. If you attempted to do so, you would create a new object.

data class Contact(val name: String, val number: String)

The ContactRow composable has a parameter of type Contact.

@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
   var selected by remember { mutableStateOf(false) }

   Row(modifier) {
      ContactDetails(contact)
      ToggleButton(selected, onToggled = { selected = !selected })
   }
}

Consider what happens when the user clicks the toggle button and the selected state changes:

  1. Compose evaluates if it should recompose the code inside ContactRow.
  2. It sees that the only argument for ContactDetails is of type Contact.
  3. Because Contact is an immutable data class, Compose is sure that none of the arguments for ContactDetails have changed.
  4. As such, Compose skips ContactDetails and does not recompose it.
  5. On the other hand, the arguments for ToggleButton have changed, and Compose recomposes that component.

Mutable objects

While the preceding example uses an immutable object, it is possible to create a mutable object. Consider the following snippet:

data class Contact(var name: String, var number: String)

As each parameter of Contact is now a var, the class is no longer immutable. If its properties changed, Compose wouldn't become aware. This is because Compose only tracks changes to Compose State objects.

Compose considers such a class unstable. Compose doesn't skip recomposition of unstable classes. As such, if Contact were defined in this way, ContactRow in the previous example would recompose any time selected changed.

Implementation in Compose

It can be helpful, though not crucial, to consider how exactly Compose determines which functions to skip during recomposition.

When the Compose compiler runs on your code, it marks each function and type with one of several tags. These tags reflect how Compose handles the function or type during recomposition.

Note: These tags aren't strictly necessary to understand recomposition and stability as described in the preceding sections of this document. However, they are broadly useful when debugging stability issues.

Functions

Compose can mark functions as skippable or restartable. Note that it may mark a function as one, both, or neither of these:

Types

Compose marks types as either immutable or stable. Each type is one or the other:

Note: A composable's parameters don't have to be immutable for Compose to consider it skippable. They can be mutable as long as the Compose runtime is notified of all changes. For most types this would be an impractical contract to uphold. However, Compose provides mutable classes that do uphold this contract for you, such as MutableState, SnapshotStateMap, and SnapshotStateList.

Debug stability

If your app is recomposing a composable whose parameters have not changed, first check its definition for parameters that are clearly mutable. Compose always recomposes a component if you pass in a type with var properties, or a val property that use a known unstable type.

For detailed information about how to diagnose complex issues with stability in Compose, see the Debug stability guide.

Fix stability issues

For information about how to bring stability to your Compose implementation, see the Fix stability issues guide.

Summary

Overall, you should note the following points:

Further reading

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026-01-16 UTC.

[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2026-01-16 UTC."],[],[]]

Web Proxy Viewer  |  New URL  |  Original Page