Thread
#compose
    louiscad

    louiscad

    2 years ago
    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
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    Compose supports state restoration via the
    savedInstanceState
    function - what else do you need?
    louiscad

    louiscad

    2 years ago
    An example with text input, a slider, and a list.
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    Just take any existing example that uses
    state
    and replace
    state
    with
    savedInstanceState
    .
    louiscad

    louiscad

    2 years ago
    I think I now see how it'd work, interesting
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    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
    .
    Adam Powell

    Adam Powell

    2 years ago
    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
    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.
    louiscad

    louiscad

    2 years ago
    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.
    Adam Powell

    Adam Powell

    2 years ago
    Interesting, I could see that falling out of some natural interface layering we'd want anyway for testing/etc.
    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?
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago
    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.
    louiscad

    louiscad

    2 years ago
    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.
    Adam Powell

    Adam Powell

    2 years ago
    @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
    @louiscad that would probably work 🙂 another good reason for the generalized key path mechanism.
    Even if you didn't use the last mile automatic keys from compose for stability
    Andrey Kulikov

    Andrey Kulikov

    2 years ago
    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
    louiscad

    louiscad

    2 years ago
    Are there composables from androidx.ui or other first party lib(s) that already use
    UiSavedStateRegistry
    ?
    Bonus question: Can we trigger state saving manually?
    Andrey Kulikov

    Andrey Kulikov

    2 years ago
    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
    louiscad

    louiscad

    2 years ago
    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 😒uspend: )
    Zach Klippenstein (he/him) [MOD]

    Zach Klippenstein (he/him) [MOD]

    2 years ago