Persisting view-state when using a custom backstack: Creating a Flow-like custom backstack (Part 4)
We’ve been creating a backstack for 3 parts now, and have solved a few problems:
- In Part 1, we’ve created a basic backstack that allowed state changes and exposed 3 convenient operators to manipulate the history list
- In Part 2, we’ve managed to provide parameters to our custom viewgroups
- In Part 3, we’ve made our backstack able to enqueue state changes while a state changer is not available, or a state change is already in progress
But we need to be able to persist the view state so that views that are removed still preserve their state, and we must also make sure we can restore this even across process death.
If you check the good ol’ Flow this example is influenced by, it did not use to have a KeyManager class, it did not have any means of persisting view state with the library.
So we’re not gonna add it to the library yet either, we’ll just add it to the example.
— — — — — — — — — — — — — — — — — — — — —
Persisting the viewstate
Actually, I can just show the commit that adds view-state persistence to our Activity, and explain afterwards. Look!
So what can we see here?
Saving the view hierarchy state
In order to save the state of our view hierarchy, there is a convenient method called
We can store this as a Parcelable, along with a few other things; and we need this to be identifiable.
The State class
We added a
State class for storing our viewstate, and it stores 3 things:
Keyof the given view (to identify this state later when we restore it)
SparseArray<Parcelable>that is the saved view hierarchy state
Bundlein case we want to add additional data to our stored state.
Parcelable so that we can persist it to Bundle in the form of
ArrayList<Parcelable>, just like we do with keys (which represent the application state).
Keeping track of the State
In order to keep track of the state, we store it in a
Map that binds it to our
Key ( so it is
We create a new entry in this map during the state changer callback (to preserve the previous view’s state, the one that we swap out and remove), and in
onSaveInstanceState() (to preserve the current view’s state).
Removing States that are no longer needed
When a state change occurs, we clear out the states we no longer need using
Restoring State after process death/config change
And when our Activity is restored, we also restore the
keyStateMap as well from the
With that, it actually works!
Now that we have solved the problem of saving our state, we’ve solved our most aching problems.
But we still have some pain points:
- we don’t have convenient lifecycle callbacks to our views for when they get created, and removed (or destroyed) ~ although maybe we could use square/coordinators for that
- you need to add a bunch of code in your Activity to integrate the backstack, and the application state/view state persistence. Maybe we could move this code out, into the library?
In the meantime, the current source code is available here.