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 and savedInstanceState composables.
They mirror remember and state, but will restore their values from a
UiSavedStateRegistry when they are first composed. This is the standard API
for saving view state, much like onSavedInstanceState in the legacy framework,
and so the backstack should support it.
This change does a few things:
When a screen is not longer visible, remove it from the composition. Note that
the ScreenWrapper remains in the composition as long as the screen's key is
in 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 set
the "hidden" semantics property on screens that aren't visible.
The ScreenWrapper holds a map of saved state values. This map, in turn, gets
saved and restored to the parent's UiSavedStateRegistry, so it can survive activity
recreations etc.
Each screen is wrapped with its own UiSavedStateRegistry that is scoped to just
that 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:
Scoping ScreenWrappers to the presence of a screen in the backstack, even though
the screen's actual composables are only alive when the screen is visible.
The mechanism that the saved state machinery uses to key values is derived from the
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 of
this same keying infrastructure.
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 mirrorremember
andstate
, but will restore their values from aUiSavedStateRegistry
when they are first composed. This is the standard API for saving view state, much likeonSavedInstanceState
in the legacy framework, and so the backstack should support it.This change does a few things:
ScreenWrapper
remains in the composition as long as the screen's key is in the active backstack, but when a screen stops being visible, we stop calling thedrawScreen
function for it. Note that this means we no longer need to set the "hidden" semantics property on screens that aren't visible.ScreenWrapper
holds a map of saved state values. This map, in turn, gets saved and restored to the parent'sUiSavedStateRegistry
, so it can survive activity recreations etc.UiSavedStateRegistry
that is scoped to just that 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 though the screen's actual composables are only alive when the screen is visible.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 of this same keying infrastructure.