[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-26 (世界標準時間)。"],[],[],null,["# Stability in Compose\n\nCompose considers types to be either stable or unstable. A type is stable if it\nis immutable, or if it is possible for Compose to know whether its value has\nchanged between recompositions. A type is unstable if Compose can't know whether\nits value has changed between recompositions.\n\nCompose uses the stability of a composable's parameters to determine whether it\ncan skip the composable during [recomposition](/develop/ui/compose/mental-model#recomposition):\n\n- **Stable parameters:** If a composable has stable parameters that have not changed, Compose skips it.\n- **Unstable parameters:** If a composable has unstable parameters, Compose always recomposes it when it recomposes the component's parent.\n\nIf your app includes many unnecessarily unstable components that Compose always\nrecomposes, you might observe performance issues and other problems.\n\nThis document details how you can increase the stability of your app to improve\nperformance and overall user experience.\n\nImmutable objects\n-----------------\n\nThe following snippets demonstrates the general principles behind stability and\nrecomposition.\n\nThe `Contact` class is an immutable data class. This is because all its\nparameters are primitives defined with the `val` keyword. Once you create an\ninstance of `Contact`, you cannot change the value of the object's properties.\nIf you attempted to do so, you would create a new object. \n\n data class Contact(val name: String, val number: String)\n\nThe `ContactRow` composable has a parameter of type `Contact`. \n\n @Composable\n fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {\n var selected by remember { mutableStateOf(false) }\n\n Row(modifier) {\n ContactDetails(contact)\n ToggleButton(selected, onToggled = { selected = !selected })\n }\n }\n\nConsider what happens when the user clicks the toggle button and the\n`selected` state changes:\n\n1. Compose evaluates if it should recompose the code inside `ContactRow`.\n2. It sees that the only argument for `ContactDetails` is of type `Contact`.\n3. Because `Contact` is an immutable data class, Compose is sure that none of the arguments for `ContactDetails` have changed.\n4. As such, Compose skips `ContactDetails` and does not recompose it.\n5. On the other hand, the arguments for `ToggleButton` have changed, and Compose recomposes that component.\n\n### Mutable objects\n\nWhile the preceding example uses an immutable object, it is possible to create a\nmutable object. Consider the following snippet: \n\n data class Contact(var name: String, var number: String)\n\nAs each parameter of `Contact` is now a `var`, the class is no longer immutable.\nIf its properties changed, Compose wouldn't become aware. This is because\nCompose only tracks changes to Compose [State objects](/reference/kotlin/androidx/compose/runtime/MutableState).\n\nCompose considers such a class unstable. Compose doesn't skip recomposition of\nunstable classes. As such, if `Contact` were defined in this way, `ContactRow`\nin the previous example would recompose any time `selected` changed.\n\nImplementation in Compose\n-------------------------\n\nIt can be helpful, though not crucial, to consider how exactly Compose\ndetermines which functions to skip during recomposition.\n\nWhen the Compose compiler runs on your code, it marks each function and type\nwith one of several tags. These tags reflect how Compose handles the function or\ntype during recomposition.\n| **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](/develop/ui/compose/performance/stability/diagnose) stability issues.\n\n### Functions\n\nCompose can mark functions as `skippable` or `restartable`. Note that it may\nmark a function as one, both, or neither of these:\n\n- **Skippable**: If the compiler marks a composable as skippable, Compose can skip it during recomposition if all its arguments are equal with their previous values.\n- **Restartable**: A composable that is restartable serves as a \"scope\" where recomposition can start. In other words, the function can be a point of entry for where Compose can start re-executing code for recomposition after state changes.\n\n### Types\n\nCompose marks types as either immutable or stable. Each type is one or the\nother:\n\n- **Immutable** : Compose marks a type as immutable if the value of its properties can never change and all methods are referentially transparent.\n - Note that all primitive types are marked as immutable. These include `String`, `Int`, and `Float`.\n- **Stable**: Indicates a type whose properties can change after construction. If and when those properties change during runtime, Compose becomes aware of those changes.\n\n| **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`.\n\nDebug stability\n---------------\n\nIf your app is recomposing a composable whose parameters have not changed, first\ncheck its definition for parameters that are clearly mutable. Compose always\nrecomposes a component if you pass in a type with `var` properties, or a `val`\nproperty that use a known unstable type.\n\nFor detailed information about how to diagnose complex issues with stability in\nCompose, see the [Debug stability](/develop/ui/compose/performance/stability/diagnose) guide.\n\nFix stability issues\n--------------------\n\nFor information about how to bring stability to your Compose implementation, see\nthe [Fix stability issues](/develop/ui/compose/performance/stability/fix) guide.\n\nSummary\n-------\n\nOverall, you should note the following points:\n\n- **Parameters**: Compose determines the stability of each parameter of your composables to determine which composables it should skip during recomposition.\n- **Immediate fixes** : If you notice your composable isn't being skipped *and\n it is causing a performance issue* , you should check the obvious causes of instability like `var` parameters first.\n- **Compiler reports** : You can use the [compiler reports](/develop/ui/compose/performance/stability/diagnose) to determine what stability is being inferred about your classes.\n- **Collections** : Compose always considers collection classes unstable, such as `List, Set` and `Map`. This is because it cannot be guaranteed that they are immutable. You can use [Kotlinx immutable collections](/develop/ui/compose/performance/stability/fix#immutable-collections) instead or annotate your classes as `@Immutable` or `@Stable`.\n- **Other modules**: Compose always considers unstable where they are from modules in which the Compose compiler does not run. Wrap the classes in UI model classes if required.\n\nFurther reading\n---------------\n\n- **Performance** : For more debugging tips on Compose performance, check out our [best practices guide](http://goo.gle/compose-performance) and [I/O talk](https://www.youtube.com/watch?v=EOQB8PTLkpY)."]]