0% found this document useful (0 votes)
13 views5 pages

Skipping Mode Enable

The document explains strong skipping in Jetpack Compose, which optimizes recomposition by skipping unchanged composables, potentially leading to issues if mutable state changes are not tracked. It provides a code example demonstrating how a toggle and a mutable list previously worked together but failed under strong skipping, and suggests using SnapshotStateList or immutable lists to ensure proper recomposition. The conclusion emphasizes the importance of correctly managing state to avoid unexpected behavior in UI updates.

Uploaded by

vivek singh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views5 pages

Skipping Mode Enable

The document explains strong skipping in Jetpack Compose, which optimizes recomposition by skipping unchanged composables, potentially leading to issues if mutable state changes are not tracked. It provides a code example demonstrating how a toggle and a mutable list previously worked together but failed under strong skipping, and suggests using SnapshotStateList or immutable lists to ensure proper recomposition. The conclusion emphasizes the importance of correctly managing state to avoid unexpected behavior in UI updates.

Uploaded by

vivek singh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Understanding Strong Skipping in Jetpack Compose

1. Introduction to Strong Skipping


In Jetpack Compose, strong skipping mode optimizes the recomposition process by ensuring
that composables are only recomposed when necessary. It skips recomposing composables
that haven't changed and avoids unnecessary work. This is generally beneficial for performance
but can introduce issues in certain scenarios where composables rely on accidental side effects,
such as when mutable state changes are not explicitly tracked.

Previously, some code might have "worked by accident," relying on implicit triggers for
recomposition (e.g., mutable state changes not being properly tracked). With strong skipping
enabled, these accidental triggers may no longer fire, causing unexpected behavior or failures
to re-render UI elements.​

2. Problem with the Code Example

@Composable​
fun MyToggle(enabled: Boolean) {}​

@Composable​
fun MyList(list: List<String>) {}​

@Composable​
fun MyScreen() {​
var list by remember { mutableStateOf(mutableListOf("Foo"))
}​
var toggle by remember { mutableStateOf(false) }​
MyToggle(toggle)​
MyList(list)​

Button(​
onClick = {​
list.add("Bar")
toggle = !toggle​
}​
) { Text("Toggle") }}
Why This Code Worked Previously
Before enabling strong skipping, the code worked because:

1.​ The toggle variable was being changed, which triggered a recomposition of MyScreen.

2.​ During this recomposition, the MyList composable was also recomposed because the list
was stored in a mutable state (mutableStateOf). The add("Bar") operation in the Button's
onClick handler would trigger the UI to re-render, even if the list itself wasn't explicitly
marked as changed.

However, this behavior was not ideal and relied on accidental side effects: the change to the
toggle was causing the recomposition of the entire screen, which in turn caused the MyList
composable to re-render.

Why It Doesn't Work with Strong Skipping


When strong skipping is enabled:

●​ Jetpack Compose optimizes recomposition by skipping composables whose state has


not explicitly changed.

●​ In this case, the list is a mutableListOf, which is a mutable object. Modifications to


mutable objects (like calling add()) do not trigger recomposition automatically.

●​ The toggle state change no longer forces the MyList composable to recompute, as the
state of list itself has not changed according to Compose's recomposition rules.

Thus, the MyList composable will be skipped during recomposition, and the UI will not update to
reflect the changes in the list.

3. How to Fix It
To ensure that MyList is properly recomposed after the list is modified, you need to ensure that
the state holding the list is observed correctly. This can be done by using SnapshotStateList or
using immutable data structures to trigger recomposition.
Using SnapshotStateList

SnapshotStateList is a type of list that supports composition and recomposition tracking,


meaning that it will trigger recomposition when its contents change.

Here’s how to modify the code to use SnapshotStateList:

@Composable​
fun MyToggle(enabled: Boolean) {}​

@Composable​
fun MyList(list: List<String>) {}​

@Composable​
fun MyScreen() {​
// Use SnapshotStateList for mutable lists​
var list by remember {
mutableStateOf(SnapshotStateList<String>()) }​
var toggle by remember { mutableStateOf(false) }​

MyToggle(toggle)​
MyList(list)​

Button(​
onClick = {​
list.add("Bar")
// Modifying the SnapshotStateList triggers recomposition​
toggle = !toggle​
}​
) { Text("Toggle") }​
}
Explanation of the Fix
●​ SnapshotStateList is a special kind of list that integrates with Compose’s state
management system. When you modify its contents (e.g., by adding or removing
elements), Compose can detect these changes and trigger the necessary recomposition.

●​ By using SnapshotStateList, the recomposition of MyList will now be correctly triggered


when the list is modified.

Alternative: Using Immutable Lists


If you prefer working with immutable lists, you can replace the
mutableStateOf(mutableListOf(...)) with an immutable list and use mutableStateOf to track the
new list after every modification:
@Composable​
fun MyScreen() {​
// Use immutable List for better Compose integration​
var list by remember { mutableStateOf(listOf("Foo")) }​
var toggle by remember { mutableStateOf(false) }​

MyToggle(toggle)​
MyList(list)​

Button(​
onClick = {​
// Create a new list, triggering recomposition​
list = list + "Bar"
// This creates a new list instance​
toggle = !toggle​
}​
) { Text("Toggle") }​
}
Explanation of This Approach
●​ Here, instead of modifying the existing list, a new list is created each time you modify it
(list + "Bar"). This change to the list triggers a recomposition of MyList because the
mutableStateOf will now hold a new instance of the list.

●​ This ensures that Compose detects the change and re-renders the composable as
needed.

4. Conclusion
With strong skipping mode enabled, composables that rely on mutable objects or accidental
state changes may not trigger recompositions as expected. This behavior can be problematic,
especially when mutable lists or other mutable state objects are involved.

To avoid these issues:

●​ Use SnapshotStateList for mutable lists, which will correctly trigger recomposition when
the list is modified.

●​ Alternatively, use immutable data structures and replace the entire list when it changes,
which will trigger recomposition naturally.

You might also like