[[["容易理解","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-09 (世界標準時間)。"],[],[],null,["# Diagnose stability issues\n\nIf you are experiencing performance issues that result from unnecessary or\nexcessive recomposition, you should debug the stability of your app. This guide\noutlines several methods for doing so.\n| **Important:** You should aim to resist unnecessary or premature optimization. Before optimizing for stability, verify you are following our [best practices\n| for Compose performance](http://goo.gle/compose-performance).\n| **Note:** If you would like more information about how to measure performance properly, see the [Macrobenchmark guide](/topic/performance/benchmarking/macrobenchmark-overview).\n\nLayout Inspector\n----------------\n\nThe Layout Inspector in Android Studio lets you see which composables are\nrecomposing in your app. It displays counts of how many times Compose has\nrecomposed or skipped a component.\n\nCompose compiler reports\n------------------------\n\nThe Compose compiler can output the results of its stability inference for\ninspection. Using this output, you can determine which of your composables are\nskippable, and which are not. The follow subsections summarize how to use these\nreports, but for more detailed information see the [technical\ndocumentation](https://github.com/JetBrains/kotlin/blob/master/plugins/compose/design/compiler-metrics.md).\n| **Warning:** You should only use this technique if you are actually experiencing performance issues related to stability. Trying to make your entire UI skippable is a premature optimization that could lead to maintenance difficulties in the future.\n\n### Setup\n\nCompose compiler reports are not enabled by default. You can activate them with\na compiler flag. The [exact setup](https://github.com/JetBrains/kotlin/blob/master/plugins/compose/design/compiler-metrics.md#enabling-metrics) varies depending on your\nproject, but for projects using the [Compose compiler gradle plugin](/develop/ui/compose/compiler) you can\nadd the following in each module's `build.gradle` file. \n\n android { ... }\n\n composeCompiler {\n reportsDestination = layout.buildDirectory.dir(\"compose_compiler\")\n metricsDestination = layout.buildDirectory.dir(\"compose_compiler\")\n }\n\nCompose compiler reports will now be generated when building your project.\n| **Important:** Make sure to always run this on a release build to ensure accurate results.\n\n#### Example output\n\nThe `reportsDestination` outputs three files. The following are example outputs\nfrom [JetSnack](https://github.com/android/compose-samples/tree/master/Jetsnack).\n\n- **`\u003cmodulename\u003e-classes.txt`:** A report on the stability of classes in this module. [Sample](https://gist.github.com/bentrengrove/9b823045a160d8a5d986bb4b31106245).\n- **`\u003cmodulename\u003e-composables.txt`:** A report on how restartable and skippable the composables are in the module. [Sample](https://gist.github.com/bentrengrove/a8ee3716a7df136144041134575f5fcb).\n- **`\u003cmodulename\u003e-composables.csv`:** A `CSV` version of the composables report that you can import into a spreadsheet or processing using a script. [Sample](https://gist.github.com/bentrengrove/2beb1b2993f68f61a7ba3ed91a1c75c9)\n\n| **Note:** The `metricsDestination` configuration produces overall statistics on the number of composables in your project and other similar info.\n| **Note:** These reports make use of the compiler tags described in the [Compose\n| stability](/develop/ui/compose/performance/stability) guide.\n\n#### Composables report\n\nThe `composables.txt` file details each composable functions for the given\nmodule, including the stability of their parameters, and whether they are\nrestartable or skippable. The following is a hypothetical example from\n[JetSnack](https://github.com/android/compose-samples/tree/master/Jetsnack): \n\n restartable skippable scheme(\"[androidx.compose.ui.UiComposable]\") fun SnackCollection(\n stable snackCollection: SnackCollection\n stable onSnackClick: Function1\u003cLong, Unit\u003e\n stable modifier: Modifier? = @static Companion\n stable index: Int = @static 0\n stable highlight: Boolean = @static true\n )\n\nThis `SnackCollection` composable is completely restartable, skippable, and\nstable. This is generally preferable, although certainly not mandatory.\n\nOn the other hand, let's take a look at another example. \n\n restartable scheme(\"[androidx.compose.ui.UiComposable]\") fun HighlightedSnacks(\n stable index: Int\n unstable snacks: List\u003cSnack\u003e\n stable onSnackClick: Function1\u003cLong, Unit\u003e\n stable modifier: Modifier? = @static Companion\n )\n\nThe `HighlightedSnacks` composable is not skippable. Compose never skips it\nduring recomposition. This occurs even if none of its parameters have changed.\nThe reason for this is the `unstable` parameter, `snacks`.\n\n#### Classes report\n\nThe file `classes.txt` contains a similar report on the classes in the given\nmodule. The following snippet is the output for the class `Snack`: \n\n unstable class Snack {\n stable val id: Long\n stable val name: String\n stable val imageUrl: String\n stable val price: Long\n stable val tagline: String\n unstable val tags: Set\u003cString\u003e\n \u003cruntime stability\u003e = Unstable\n }\n\nFor reference, the following is the definition of `Snack`: \n\n data class Snack(\n val id: Long,\n val name: String,\n val imageUrl: String,\n val price: Long,\n val tagline: String = \"\",\n val tags: Set\u003cString\u003e = emptySet()\n )\n\nThe Compose compiler has marked `Snack` as unstable. This is because the type of\nthe `tags` parameter is `Set\u003cString\u003e`. This is an immutable type, given that it\nis not a `MutableSet`. However, standard collection classes such as `Set`,\n`List`, and `Map` are ultimately interfaces. As such, the underlying\nimplementation may still be mutable.\n\nFor example, you could write `val set: Set\u003cString\u003e = mutableSetOf(\"foo\")`. The\nvariable is constant and its declared type is not mutable, but its\nimplementation is *still* mutable. The Compose compiler cannot be sure of the\nimmutability of this class as it only sees the declared type. It therefore marks\n`tags` as unstable.\n| **Important:** For information about how to bring stability to an unstable class such as this, see the [Fix stability issues](/develop/ui/compose/performance/stability/fix) guide."]]