One Off the Slack: Stability Now!

Maik had a MutableList parameter to a MyList() composable and was wondering why MyList() would recompose, even if that MutableList did not change.

The problem is that while Maik knows that the list did not change, Compose does not. As Google’s Jim Sproch put it:

MyList(items) takes in a MutableList, which is (as the name suggests) mutable, so Compose can’t know if that list has been modified or not, so it needs to be conservative and rerun that code. If you use a list implementation that is stable (like SnapshotStateList) then MyList(items) is less likely to run.

Even a List would be insufficient, as that simply prevents one from modifying what elements are in the list — the contents of the elements themselves could change.

In general, composable functions work best with truly immutable contents, and that will require using types that Compose know are truly immutable (e.g., ones with the @Stable annotation).

Jim also points out a key risk:

…keep in mind that your code should NEVER make assumptions about when composables will run. Compose is free to run composable functions for any reason and at any time, at its sole discretion.

This has the potential of being an ongoing problem with Compose development, relying on side-effects from composition. A composable should be idempotent: whether it gets called zero, one, two, or a thousand times should have no impact on the rest of the app.

Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!