Is the suggested way of working with `LazyColumn/L...
# compose
e
Is the suggested way of working with
LazyColumn/LazyRow
to use mutable state for the items, so that updating a property of a single item doesn't cause all the visible items to recompose?
f
e
I am, but I'm still seeing all visible items recompose if I don't use mutable state (i.e. I use a SnapshotStateList and call
set
with the new element that has a stable key)
c
Do you use
List
? I ask that because
List
is not stable.
e
I'm using
SnapshotStateList
Did some more digging and it looks like the primary purpose of
SnapshotStateList
is to have an observable list state, and not necessarily to reduce the scope of recomposition.
c
SnapshotStateList
is also
@Stable
so if you pass that the a composable, it should enable skipping and smart recompositions.
e
@Csaba Kozák that doesn't seem to be the case unless I'm not understanding its source, and doing something wrong in my code. As far as I can tell, it's a mutable view of an immutable list, in that mutations copy the list and update the state with the new copy. It's mostly the same as
MutableState<List>
just with a different mechanism of action (and maybe some extra/different optimizations). In both cases adding/removing from the list will cause all visible items to recompose, as will updating a specific element. I believe this is because the list is passed to the
items
function, and so that gets recomposed, which in turn either recomposes or recreates all of the items. If that's acceptable for performance, then I guess that's fine, but if it's not then something needs to be done. The only way I've found to achieve that is to make the elements of the list use
MutableState
for all properties, which is not the most ideal (from an architecture / data design perspective)
s
Regarding (premature avoiding?) recomposition, we had an interesting discussion over on Twitter, unfortunately with no clear outcome: https://twitter.com/CatalinGhita4/status/1455871599245148167 Experts: should we generally annotate state data classes with „@Stable“ to avoid overcomposition? If yes, then I feel this should be more emphasized in the documentation. But maybe this isn’t even a thing to worry about?
e
I had this conversation a few months ago, and it seems like recomposing at the root, and relying on skipping is fine. However, a later conversation (that I can't find now) cautioned that you have to be careful, because if you get the equality wrong for something and you recompose really high up in the tree, it can cause performance issues (I think it was in the context of lists because of how they work with equality). My issue in the current thread is more about whether we should be concerned about eliminating as much recomposition as possible in scenarios where we don't rely on skipping (i.e. with
State
). For example, should I be concerned that mutating a
SnapshotStateList
causes all visible items to recompose. I think the answer is the standard "it depends" and "profile as necessary" that comes with optimization, but I'm not 100% if it falls under the same category as that.
🙏 1
z
I’ve been assuming that any unnecessary recomposition is a “bad thing”,
The question in essence is if we should be generally reducing recomposition as much as possible, or if we should only aim to do that if there are performance issues that come up.
Optimizing to reduce all possible unnecessary recompositions too early has the pitfalls of any premature optimization. The compose compiler and runtime already do a lot of work to avoid unnecessary work, and often recomposing a function ends up being less work than it looks if all the other composables it calls skip. So to answer your original question, using an immutable list is probably fine. The first thing to do would be decide whether using an immutable or mutable list makes the code simpler.
should we generally annotate state data classes with „@Stable” to avoid overcomposition?
No, since the compiler should already infer data classes as stable. It’s very easy to get trigger-happy with
@Stable
annotations and suddenly you’ve got unstable classes that are incorrectly annotated and that will result in bugs.
👍 2
🙏 1
s
Just FYI, regarding skipping and the above Twitter thread, Jim Sproch chimed in https://mobile.twitter.com/JimSproch/status/1456008752159621120 It looks that we just have overlooked to annotate our state data classes with
@Immutable
and therefore experienced no skipping / deep recompositions when using monolithic state classes. Will try that out today. EDIT: Not working as expected: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1636009011389800
z
Again, the compiler should infer that data classes are stable automatically in most cases and you shouldn't need to annotate them.
Ah, you’re dealing with lists, which aren’t inferrable as stable
193 Views