One Off the Slack: How Do We Remember Across Configuration Changes?
Rick Regan asked:
I want to remember scroll state across configuration changes within a Text with modifier
.verticalScroll(scrollState)
.
val scrollState = rememberScrollState()
does not survive a configuration change.val scrollState = rememberSaveable { ScrollState(0) }
gets an exception “ScrollState@fb46372 cannot be saved using the current SaveableStateRegistry”.val scrollState = ScrollState(0)
globally outside of any Composable works, but this is putting the scroll state outside the scope of the Composable. Is it OK to do that? Is there another way
I have a fixed height
Text
that I’ve scrolled down into. When I rotate, the text is still there and in its proper scroll position when I use the third option.
When Google’s Ian Lake pointed out that rememberScrollState()
uses rememberSaveable()
, Rick did a bit
more testing, and eventually concluded:
I know what it is. I use the same element in both configurations, with logic like
if (maxWidth < 500.dp) {
MyComposable()
} else {
MyComposable()
}
So each one gets its own fresh
ScrollState
. (The text they display is in my app state.) To fix it, I have to hoistrememberScrollState
. If I put it in that top-level composable then I have to pass it down through many layers of composables (not shown). That makes option 3 above (val scrollState = ScrollState(0)
in my app state) more appealing. But is that bad practice?
Ian mentioned that there was a gap in the plan:
Well, option 3 won’t actually help with process death and recreation (i.e., what you test when you enable the ‘Don’t keep activties’ developer option); you really do need to save it and restore it at some level
Rick conceded that rememberSaveable()
probably was the right answer, though he expressed some trepidation:
Thanks, I was overlooking process death (which is down there on my todo list 🙂). Obviously then I’ll also have to save the accompanying text with
rememberSaveable
. I have the text astext by mutableStateOf()
in my “view model” (not actually ViewModel); so looking ahead: isrememberSaveable(text) { text }
(at an appropriate-level composable) the way to do it so that it keeps updating the “save”?
Ian confirmed:
If that text hasn’t been actually persisted to disk, yep, you’ll want to use
rememberSaveable
Read the original thread in the kotlinlang Slack workspace. Not a member? Join that Slack workspace here!