Assigned
Status Update
Comments
an...@google.com <an...@google.com>
al...@google.com <al...@google.com> #2
Triage notes: We should consider this, but it needs more thought. Not possible to avoid collisions in general given the current design.
er...@gmail.com <er...@gmail.com> #3
I found a strange problem with using nested LazyLayout that I thought related to this discussion (rememberSaveable).
I attached two videos to demonstrate this issue.
In the state_loss video, you can sometimes see the state in rememberSaveable
losses (changing the numbers of row two) but in state_preserve video if you wrap item content with moveableContentOf
there's no state losing.
@Composable
fun InnerStateLossWhenScrolling() {
LazyColumn {
items(30) {
LazyRow {
items(20) {
val randomN = rememberSaveable { Random.nextInt() }
Text(
text = randomN.toString(),
modifier = Modifier.padding(horizontal = 8.dp),
fontSize = 36.sp
)
}
}
}
}
}
@Composable
fun InnerStateSavedEvenScrolling() {
LazyColumn {
items(30) {
LazyRow {
items(20) {
movableContentOf {
val randomN = rememberSaveable { Random.nextInt() }
Text(
text = randomN.toString(),
modifier = Modifier.padding(horizontal = 8.dp),
fontSize = 36.sp
)
}()
}
}
}
}
}
Description
Currently,
rememberSaveable
optionally takes akey
.If
null
or the empty string is passed as thekey
(withnull
being the default), thecurrentCompositeKeyHash
is used as the backing key for saving into saved instance state. This makesrememberSaveable
function very similarly toremember
: state is positionally memoized, and the equivalent ofkeys
forremember
are represented asinputs
forrememberSaveable
. Two different calls torememberSaveable
from two different locations in the source code won't share state.However, if a non-empty string is passed as a
key
torememberSaveable
, thecurrentCompositeKeyHash
is not used at all, and the key being used to save into instance state is directly specified by the non-emptykey
passed torememberSaveable
.This has some strange effects, that run counter to the normal usage of Compose and
remember
:rememberSaveable
is now partially positionally memoized, but not entirely. If you have two differentrememberSaveable
s called from two different locations in the source code in composition at the same time, they won't share state, even if they use the same manually specifiedkey
. But, state can be shared between them if separated in time (before and after state instance saving happens)rememberSaveable
s sharing state with the same key, this behavior is now extremely tied to when saved instance state is saved, and when therememberSaveable
s enter and leave composition.LocalSaveableStateRegistry
). Unrelated sections of code could interact with each other unpredictably if the key is not globally unique. Having to deal with this "globalness" is a bit strange.With these strange effects, it doesn't seem like manually specifying a
key
gains much in terms of functionality, and the functionality it does potentially gain in sharing state across composition feels like the wrong approach in Compose.Therefore, it might make sense to deprecate the overloads of
rememberSaveable
that take akey
, and instead just use thecurrentCompositeKeyHash
in all cases.