Start using UiSavedStateRegistry to preserve screen "view" state. #25
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently screens' states are saved as long as the Backstack is in the composition
by being kept entirely alive. This is not efficient, it's equivalent to keeping
all views in the backstack attached at all times. Ideally we would only keep screens
in the composition while they are actually visible, and remove all hidden screens as
soon as possible. Unfortunately, until dev08, the only way to preserve view state
was to keep these screens composed.
Dev08 introduces
rememberSavedInstanceState
andsavedInstanceState
composables.They mirror
remember
andstate
, but will restore their values from aUiSavedStateRegistry
when they are first composed. This is the standard APIfor saving view state, much like
onSavedInstanceState
in the legacy framework,and so the backstack should support it.
This change does a few things:
the
ScreenWrapper
remains in the composition as long as the screen's key isin the active backstack, but when a screen stops being visible, we stop calling
the
drawScreen
function for it. Note that this means we no longer need to setthe "hidden" semantics property on screens that aren't visible.
ScreenWrapper
holds a map of saved state values. This map, in turn, getssaved and restored to the parent's
UiSavedStateRegistry
, so it can survive activityrecreations etc.
UiSavedStateRegistry
that is scoped to justthat screen. This registry is asked to save values to the above map when the screen
is going to be hidden, and is re-created to restore from the cached values when it
is shown.
The keys to making this work are:
ScreenWrapper
s to the presence of a screen in the backstack, even thoughthe screen's actual composables are only alive when the screen is visible.
positional memoization keys. The only way this works is because those keys remain
static even when a composable is removed and re-added later. Because that happens,
and because those keys are globally unique (at least within the composition), the
individual screen registries don't need to do any scoping of their keys, and we don't
need to worry about somehow turning the screen keys (
T
) into state keys (String
).The one thing I haven't verified is if these keys stay constant even if items in the
hidden backstack are reordered, but I expect they will since
@Pivotal
makes use ofthis same keying infrastructure.