### Stability Configuration File Example Source: https://developer.android.com/develop/ui/compose/performance/stability/fix An example of a stability configuration file used with the Compose compiler. It shows how to specify classes to be considered stable, including support for wildcards and generic types. ```text // Consider LocalDateTime stable java.time.LocalDateTime // Consider my datalayer stable com.datalayer.* // Consider my datalayer and all submodules stable com.datalayer.** // Consider my generic type stable based off it's first type parameter only com.example.GenericClass<*,_> ``` -------------------------------- ### Dynamic Background Color with Lambda Modifier (Optimized Draw Phase) Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This example demonstrates optimizing a frequently changing state (color) used in a modifier. Instead of directly applying the color, `drawBehind` is used with a lambda. This ensures the color state is only read during the draw phase, skipping composition and layout when the color changes. ```kotlin val color by animateColorBetween(Color.Cyan, Color.Magenta) Box( Modifier .fillMaxSize() .drawBehind { drawRect(color) } ) ``` -------------------------------- ### Analyze Composables Stability Report Source: https://developer.android.com/develop/ui/compose/performance/stability/diagnose This example demonstrates the output of a composables report, detailing the stability of parameters for a 'SnackCollection' composable. It shows that all parameters are 'stable', indicating the composable is fully restartable and skippable. ```kotlin restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun SnackCollection( stable snackCollection: SnackCollection stable onSnackClick: Function1 stable modifier: Modifier? = @static Companion stable index: Int = @static 0 stable highlight: Boolean = @static true ) ``` -------------------------------- ### Lambda Memoization with Strong Skipping - Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability/strongskipping This example shows how the Compose compiler automatically wraps lambdas within composables with a `remember` call when strong skipping mode is enabled. The lambda is keyed by its captured unstable and stable parameters, ensuring efficient memoization. ```kotlin @Composable fun MyComposable(unstableObject: Unstable, stableObject: Stable) { val lambda = remember(unstableObject, stableObject) { { use(unstableObject) use(stableObject) } } } ``` -------------------------------- ### Identify Unstable Composables Source: https://developer.android.com/develop/ui/compose/performance/stability/diagnose This example shows a composable function 'HighlightedSnacks' with an 'unstable' parameter 'snacks'. This instability prevents the composable from being skipped during recomposition, even if its parameters haven't changed, potentially leading to performance issues. ```kotlin restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks( stable index: Int unstable snacks: List stable onSnackClick: Function1 stable modifier: Modifier? = @static Companion ) ``` -------------------------------- ### Immutable Data Class Example in Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability Demonstrates an immutable data class in Kotlin using the `val` keyword for all properties. This ensures that once an object is created, its state cannot be changed, which is a key factor for stability in Compose. ```kotlin data class Contact(val name: String, val number: String) ``` -------------------------------- ### Opt-out of Strong Skipping with @NonSkippableComposable - Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability/strongskipping This example demonstrates how to prevent a composable function from being skipped during recomposition, even when strong skipping mode is enabled. The `@NonSkippableComposable` annotation is used for this purpose, ensuring the composable is always recomposed if its parent is. ```kotlin @NonSkippableComposable @Composable fun MyNonSkippableComposable {} ``` -------------------------------- ### Mutable Data Class Example in Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability Illustrates a mutable data class in Kotlin where properties are declared with `var`. This makes the object mutable, and Compose treats such classes as unstable, leading to potential performance issues due to unnecessary recompositions. ```kotlin data class Contact(var name: String, var number: String) ``` -------------------------------- ### Compose Compiler Gradle Plugin Stability Configuration Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Demonstrates how to configure the Compose compiler Gradle plugin to use a stability configuration file. This is done within the `composeCompiler` options block. ```kotlin composeCompiler { stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf") } ``` -------------------------------- ### Basic Scrollable List State Observation in Jetpack Compose Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This snippet demonstrates a common scenario in Jetpack Compose where the visibility of a button is tied to the scroll state of a `LazyColumn`. It highlights a potential performance issue where rapid state changes can lead to excessive recompositions. ```kotlin val listState = rememberLazyListState() LazyColumn(state = listState) { // ... } val showButton = listState.firstVisibleItemIndex > 0 AnimatedVisibility(visible = showButton) { ScrollToTopButton() } ``` -------------------------------- ### Composable with ImmutableList Parameter Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Shows how to use kotlinx.collections.immutable.ImmutableList to ensure compile-time safety for immutability. This approach helps in making the parameter stable. ```kotlin @Composable private fun HighlightedSnacks( … snacks: ImmutableList, … ) ``` -------------------------------- ### Optimize Lazy Layouts with Stable Item Keys in Compose Source: https://developer.android.com/develop/ui/compose/performance/bestpractices Improve recomposition performance in lazy layouts (`LazyColumn`, `LazyRow`) by providing stable, unique keys for each item. This allows Compose to correctly identify moved items, preventing unnecessary recompositions of unchanged data. ```kotlin @Composable fun NotesList(notes: List) { LazyColumn { items( items = notes ) { note -> NoteRow(note) } } } PerformanceSnippets.kt ``` ```kotlin @Composable fun NotesList(notes: List) { LazyColumn { items( items = notes, key = { note -> // Return a stable, unique key for the note note.id } ) { note -> NoteRow(note) } } } PerformanceSnippets.kt ``` -------------------------------- ### Configure Compose Compiler Reports in Gradle Source: https://developer.android.com/develop/ui/compose/performance/stability/diagnose This configuration enables the generation of Compose compiler reports and metrics by specifying output directories within the module's build.gradle file. It's essential for debugging recomposition issues. ```gradle android { ... } composeCompiler { reportsDestination = layout.buildDirectory.dir("compose_compiler") metricsDestination = layout.buildDirectory.dir("compose_compiler") } ``` -------------------------------- ### Optimizing Scrollable List UI with derivedStateOf in Jetpack Compose Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This snippet showcases the optimized approach using `derivedStateOf` in Jetpack Compose. By wrapping the state derivation in `derivedStateOf`, recompositions are limited to when the `firstVisibleItemIndex` actually changes, significantly improving performance. ```kotlin val listState = rememberLazyListState() LazyColumn(state = listState) { // ... } val showButton by remember { derivedStateOf { listState.firstVisibleItemIndex > 0 } } AnimatedVisibility(visible = showButton) { ScrollToTopButton() } ``` -------------------------------- ### Annotate Classes as Stable for Object Equality - Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability/strongskipping This code illustrates how to mark a class with the `@Stable` annotation. This is useful when you want Compose to use object equality (`Object.equals()`) instead of instance equality (`===`) for comparing instances of that class, particularly when dealing with data that might be frequently reallocated. ```kotlin @Stable class MyStableClass { ... } ``` -------------------------------- ### Defer State Read with Lambda in Composable (Before Optimization) Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This snippet shows a basic implementation where scroll state is passed directly to a composable. When the scroll state changes, it causes the parent composable to recompose, which can be inefficient. This is the state before applying the optimization. ```kotlin @Composable fun SnackDetail() { // ... Box(Modifier.fillMaxSize()) { // Recomposition Scope Start val scroll = rememberScrollState(0) // ... Title(snack, scroll.value) // ... } // Recomposition Scope End } @Composable private fun Title(snack: Snack, scroll: Int) { // ... val offset = with(LocalDensity.current) { scroll.toDp() } Column( modifier = Modifier .offset(y = offset) ) { // ... } } ``` -------------------------------- ### Use Lambda-Based Modifier for Offset (Optimized Layout Phase) Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This snippet further optimizes the `Title` composable by using the lambda version of the `Modifier.offset`. This allows the scroll state to be read directly in the layout phase, skipping the composition phase entirely when the state changes. This is ideal for frequently changing state used for layout adjustments. ```kotlin @Composable private fun Title(snack: Snack, scrollProvider: () -> Int) { // ... Column( modifier = Modifier .offset { IntOffset(x = 0, y = scrollProvider()) } ) { // ... } } ``` -------------------------------- ### Wrapper Class for Stable List Parameter Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Illustrates creating a custom immutable data class to wrap a List. This wrapper class can then be used as a stable parameter type in composables. ```kotlin @Immutable data class SnackCollection( val snacks: List ) ``` -------------------------------- ### Defer State Read with Lambda in Composable (After Optimization) Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This optimized version defers the reading of the scroll state by passing a lambda function to the `Title` composable. This ensures the state is only read when needed within `Title`, reducing the scope of recomposition. The scroll state is now provided as a `() -> Int`. ```kotlin @Composable fun SnackDetail() { // ... Box(Modifier.fillMaxSize()) { // Recomposition Scope Start val scroll = rememberScrollState(0) // ... Title(snack) { scroll.value } // ... } // Recomposition Scope End } @Composable private fun Title(snack: Snack, scrollProvider: () -> Int) { // ... val offset = with(LocalDensity.current) { scrollProvider().toDp() } Column( modifier = Modifier .offset(y = offset) ) { // ... } } ``` -------------------------------- ### Enable Strong Skipping Mode in Gradle - Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability/strongskipping This snippet shows how to enable the strong skipping mode for a Gradle module. It's enabled by default in Kotlin 2.0.20 and later. For earlier versions, you need to explicitly set `enableStrongSkippingMode = true` within the `composeCompiler` block of your `build.gradle` file. ```kotlin android { ... } composeCompiler { enableStrongSkippingMode = true } ``` -------------------------------- ### Stable and Restartable Composable Signature Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Shows the resulting signature of a composable function after applying stability improvements, such as using immutable collections or wrapper classes. Parameters are marked as 'stable'. ```kotlin restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks( stable index: Int stable snacks: ImmutableList stable onSnackClick: Function1 stable modifier: Modifier? = @static Companion ) ``` -------------------------------- ### Minimize Expensive Calculations with `remember` in Compose Source: https://developer.android.com/develop/ui/compose/performance/bestpractices Avoid re-sorting lists on every recomposition by using the `remember` function to cache the results of expensive calculations. This ensures sorting happens only when necessary, improving performance, especially for frequently recomposed composables like those in `LazyColumn`. ```kotlin @Composable fun ContactList( contacts: List, comparator: Comparator, modifier: Modifier = Modifier ) { LazyColumn(modifier) { // DON’T DO THIS items(contacts.sortedWith(comparator)) { contact -> // ... } } } PerformanceSnippets.kt ``` ```kotlin @Composable fun ContactList( contacts: List, comparator: Comparator, modifier: Modifier = Modifier ) { val sortedContacts = remember(contacts, comparator) { contacts.sortedWith(comparator) } LazyColumn(modifier) { items(sortedContacts) { // ... } } } PerformanceSnippets.kt ``` -------------------------------- ### Use Immutable Collections in Compose Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Demonstrates how to replace standard mutable collections with immutable ones to ensure class stability in Jetpack Compose. This is crucial because the Compose compiler often flags default collections as unstable. Using Kotlinx Immutable Collections guarantees immutability, allowing the Compose compiler to treat the class as stable. ```kotlin import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentSetOf data class Snack { val tags: ImmutableSet = persistentSetOf() } ``` -------------------------------- ### Composable with Stable Wrapper Parameter Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Demonstrates a composable function using the custom SnackCollection wrapper class as a stable parameter. This allows Compose to mark the parameter as stable. ```kotlin @Composable private fun HighlightedSnacks( index: Int, snacks: SnackCollection, onSnackClick: (Long) -> Unit, modifier: Modifier = Modifier ) ``` -------------------------------- ### Compose Compiler Stability Report for Snack Class Source: https://developer.android.com/develop/ui/compose/performance/stability/diagnose This snippet shows the output of the Compose compiler's stability report for the 'Snack' class, indicating its runtime stability status and the stability of its properties. It helps in understanding how the compiler analyzes class composition. ```kotlin unstable class Snack { stable val id: Long stable val name: String stable val imageUrl: String stable val price: Long stable val tagline: String unstable val tags: Set = Unstable } ``` -------------------------------- ### Avoid Backwards Writes in Jetpack Compose Source: https://developer.android.com/develop/ui/compose/performance/bestpractices This composable demonstrates a backwards write, where state is updated after being read within the same composable function. This can cause infinite recompositions. The correct approach is to update state in response to events, such as button clicks. ```kotlin @Composable fun BadComposable() { var count by remember { mutableIntStateOf(0) } // Causes recomposition on click Button(onClick = { count++ }, Modifier.wrapContentSize()) { Text("Recompose") } Text("$count") count++ // Backwards write, writing to state after it has been read } ``` -------------------------------- ### Composable with Unstable List Parameter Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Demonstrates a composable function that takes a List of Snack objects as a parameter. By default, Compose marks List parameters as unstable, even if the contained type is stable. ```kotlin restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks( … unstable snacks: List … ) ``` -------------------------------- ### Definition of the Snack Data Class Source: https://developer.android.com/develop/ui/compose/performance/stability/diagnose This snippet provides the Kotlin data class definition for 'Snack'. It includes the properties and their default values, which are relevant for understanding the class's structure and how it's used in Compose. ```kotlin data class Snack( val id: Long, val name: String, val imageUrl: String, val price: Long, val tagline: String = "", val tags: Set = emptySet() ) ``` -------------------------------- ### Annotate Class as Immutable in Compose Source: https://developer.android.com/develop/ui/compose/performance/stability/fix Shows how to apply the `@Immutable` annotation to a data class in Jetpack Compose. This annotation explicitly tells the Compose compiler that the class's properties will never change after instantiation, overriding any potential compiler inferences about mutability and ensuring the class is treated as stable. ```kotlin import androidx.compose.runtime.Immutable @Immutable data class Snack( // ... properties ) ``` -------------------------------- ### Avoid Lambda Memoization with @DontMemoize Annotation (Kotlin) Source: https://developer.android.com/develop/ui/compose/performance/stability/strongskipping Use the @DontMemoize annotation to explicitly prevent the Kotlin compiler from memoizing a lambda expression in Jetpack Compose. This is useful when you need to ensure a lambda is re-evaluated on every call, rather than relying on cached results. No specific dependencies are required beyond the Compose compiler. ```kotlin val lambda = @DontMemoize { // Code to be executed without memoization ... } ``` -------------------------------- ### Composable with Immutable Parameter in Kotlin Source: https://developer.android.com/develop/ui/compose/performance/stability Shows a Compose UI element (`ContactRow`) that accepts an immutable `Contact` object as a parameter. Compose can optimize recomposition for this composable because the `Contact` type is stable. ```kotlin @Composable fun ContactRow(contact: Contact, modifier: Modifier = Modifier) { var selected by remember { mutableStateOf(false) } Row(modifier) { ContactDetails(contact) ToggleButton(selected, onToggled = { selected = !selected }) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.