Dominaezzz
11/18/2020, 11:30 PMSnapshotStateList<T>
and MutableState<List<T>>
? In particular, is there any difference in the granularity of how mutations trigger recomposition? (Like in a LazyColumnFor
)Adam Powell
11/18/2020, 11:35 PMDominaezzz
11/18/2020, 11:54 PMAdam Powell
11/19/2020, 12:48 AMLeland Richardson [G]
11/19/2020, 6:02 AMSnapshotStateList<T>
as a fancy version of MutableState<List<T>>
.
When you’re using the latter, you’re essentially treating the list itself as an immutable piece of data, and whenver you want to change it, you have to provide a whole new list. So for example, to add an item in the middle of the list:
state.value =
state.value.let {
it.subList(0, n) + item + it.subList(n)
}
This is because the “tracking” is really done on a single value, not on the individual elements of the list. You have a “tracked” reference to a list, and you’re updating what that reference points to.
On the other hand, the SnapshotStateList is made to look like a MutableList, but all mutations are tracked properly by Compose.
For instance, adding an element in the middle of the list is just:
state.insertAt(n, item)
This is really handy if you’re really thinking of the list and its elements as the stateful part of your app. However, I tend to lean away from SnapshotStateList in most cases just because I think the MutableState<List> variant is not going to be any worse performance wise and it introduces fewer new concepts into your app (ie, you are probably already familiar using both MutableState and List all over the place, but likely not SnapshotStateList).
That said, it can be very useful in specific situations.Adam Powell
11/19/2020, 6:31 AMDominaezzz
11/19/2020, 9:51 AMSnapshot
in the name is somewhat misleading. I think the name MutableStateList
would have more/less helped me quickly appreciate the difference.Dominaezzz
11/19/2020, 9:52 AMAdam Powell
11/19/2020, 3:01 PMmutableStateListOf
: SnapshotStateList
:: mutableListOf
: ArrayList
- the factory method speaks to the interface you'll get back but the concrete type describes itself rather than the interface it implements