https://kotlinlang.org logo
l

louiscad

06/25/2020, 1:07 PM
Hello, people from Flutter made an extensive document about state restoration and their plans (since it's not supported natively yet). When it comes to Jetpack Compose, I've not seen much about facilities to ease state saving (yet), so I'm wondering if that document could help shape the APIs that we can use to support state restoration easily. Here it is: https://flutter.dev/go/state-restoration-design
👍 2
z

Zach Klippenstein (he/him) [MOD]

06/25/2020, 1:15 PM
Compose supports state restoration via the
savedInstanceState
function - what else do you need?
l

louiscad

06/25/2020, 1:16 PM
An example with text input, a slider, and a list.
z

Zach Klippenstein (he/him) [MOD]

06/25/2020, 1:18 PM
Just take any existing example that uses
state
and replace
state
with
savedInstanceState
.
l

louiscad

06/25/2020, 1:19 PM
I think I now see how it'd work, interesting
z

Zach Klippenstein (he/him) [MOD]

06/25/2020, 1:21 PM
I think
RestorationManager
in this doc roughly corresponds to
UiSavedStateRegistry
,
RestorationId
to whatever key is used for
savedInstanceState
(the positional memoization key by default), and
RestorationScope
to the ambient that holds the
UiSavedStateRegistry
.
a

Adam Powell

06/25/2020, 1:23 PM
One other thing we've talked about doing not just for saved state but for other types of stable composition scope keying is some sort of
Path("key") { }
nesting that I think roughly parallels the nested bucket approach described here
👍 3
This sort of thing also ends up being useful for things like activity result launchers via the new activity result jetpack lib
In particular the ability to get a developer-specified yet incrementally built identifier and use the composition key for the last mile means a ton of structure above the last explicit path marker can change for different configurations, etc.
🙌 2
l

louiscad

06/25/2020, 1:26 PM
Something that'd really like is to be able to swap system savedInstance state by a custom alternative, very easily, that could then send those values over, for something like Handoff on iOS & macOS. That could also be used to sync reading position or alike, and have some state persist when coming back.
a

Adam Powell

06/25/2020, 1:27 PM
Interesting, I could see that falling out of some natural interface layering we'd want anyway for testing/etc.
🎉 1
So far though we've been leaning towards state restoration as being an initial value thing and not something that happens later and requires developers to perform a merge
Waiting for a cloud sync to potentially time out seems like a big hurdle to that, and the merging requirement sounds like it could introduce a lot of complexity for developers who don't need or want it
What do you think?
z

Zach Klippenstein (he/him) [MOD]

06/25/2020, 1:30 PM
The Handoff use case seems like you could do with a custom function similar to
savedInstanceState
. You'd have to explicitly call that function instead of magically swapping it in, but it seems like the behavior would be different enough anyway (what Adam said, two way syncing?, Etc) that the opt-in would be safer.
@Adam Powell is there a way to subscribe to state changes on a
State
from non-compose code yet? Once that's available, you could build something like this on top of that with some coroutines and something like Store.
l

louiscad

06/25/2020, 1:34 PM
I was thinking there'd be two things: 1. Configuration and initialization of the
savedInstanceState
substitute (which might involve a suspending logic, and "linking" to an error handling logic) 2. Explicitedness about the actual key use for saving some data, to allow long term storage (i.e. not limited to the app version), without conflicts For merging, I was thinking it'd be something to handle in the logic of the
savedInstanceState
substitude.
a

Adam Powell

06/25/2020, 1:36 PM
@Zach Klippenstein (he/him) [MOD] There always has been but it's been pretty raw to use. This just went in and should make it easier https://android-review.googlesource.com/c/platform/frameworks/support/+/1326201
🙌 2
@louiscad that would probably work 🙂 another good reason for the generalized key path mechanism.
👍 1
Even if you didn't use the last mile automatic keys from compose for stability
a

Andrey Kulikov

06/25/2020, 5:11 PM
and yes, you can provide your own
UiSavedStateRegistry
with an ambient where you can do your own saving and restoration as it is nicely abstracted
👌 1
l

louiscad

06/25/2020, 5:16 PM
Are there composables from androidx.ui or other first party lib(s) that already use
UiSavedStateRegistry
?
Bonus question: Can we trigger state saving manually?
a

Andrey Kulikov

06/25/2020, 5:32 PM
yes, text fields and scrollers are saving the state already
and yes, you can gather the registry using an ambient and call performSave() on it
l

louiscad

06/25/2020, 5:45 PM
Thank you very much for your answers, I think I'll experiment with persisting state periodically later this summer (but not do I/O on the main thread ⏸️ )
z

Zach Klippenstein (he/him) [MOD]

06/25/2020, 6:31 PM
I’ve got a proof-of-concept project that uses the saved state registry manually: https://github.com/zach-klippenstein/compose-backstack/blob/5fe89af17b9dc48ee28bea3e95c020ce353ff31b/compose-backstack/src/main/java/com/zachklipp/compose/backstack/ChildSavedStateRegistry.kt (thanks to @grandstaish for fixing my bugs 😅)
👀 1
👍🏼 1
4 Views