Saving And Restoring Navigation Stack (And Other App State) Between Sessions

My app tends to have a deep navigation stack (dozens of pages on a normal browsing session) and users expect the app to restore completely each time they load it up. As noted elsewhere online the OS may kill your app when in the background and when it does the app will have to do a fresh start the next time the user loads it, losing the browsing history from the last session. As far as I can tell Ionic doesn’t have a built-in way to persist app state between sessions (at least it didn’t in v1, that may be changing in v2) so it’s up to me to build a solution for my app.

My question is how do I go about doing this? At a high level it seems like each time the navigation stack changes I want to write the current app state (at least the stack of pages) to a permanent storage (probably using SqlStorage). I know I can use NavController.getByIndex() to get each of the view controllers for the current stack but how would I go about saving and restoring those? I can imagine manually collecting the relevant state data from each of the pages and then using NavController.insertPages() to rebuild the stack at startup. While that seems viable it also feels like a hack. Does anyone have experience with this? Is there a better way to persist app state between sessions?

This is tough one, and one that I think is best to leave alone.

So say you’re app is in the background. You’d have to take a snapshot of the Stack on pause, and save that snapshot to storage. Then on startup, set the pages based on that snapshot using navcontroller

Personally, I think this is a bit much and overkill really.

I agree, it feels like more work that I should have to do at the app level. That said this is still functionality that I need for my app; the behavior otherwise provides a very bad user experience. Do you have any recommendations for going about it? setPages() seems more appropriate than insertPages(), but if I could entirely avoid having to manually persist app state that would be best.

Not a whole lot we can do about that though. If the OS clears things out, then thats what the OS does.

True, there’s no way to avoid the OS killing the app in the background (and I certainly don’t think there should be), however being able to persist app state to disk in order to restore the app between sessions is important. Ionic currently provides the tools needed for developers to do that (SqlStorage provides a way to write to permanent storage which is all that’s technically needed) but it doesn’t offer any help. I don’t think that’s necessarily a problem; It seems to me like persisting app state will generally be an app-specific affair.

When I said I’d like to “avoid having to manually persist app state” I meant that it would be nice if Ionic had some system for doing this automatically. Perhaps this is something that can be build into a third-party library, in which case it wouldn’t need to be part of Ionic-core. At this point I’m not experienced enough with Ionic or Angular to say for certain. I suspect that between Angular and Ionic there’s enough information that, with a few more lifecycle hooks, it should to possible to make persisting app state automatic while still giving developers room to handle any app-specific details that they need to.

Have you come up with a solution for this? Specifically, I’m being asked that when the app is dismissed (in ios with the swipe) the user session and ui state are preserved. Also the OS may also kill the app while running in the background. The default behavior is an app reset which brings the user back to the login screen which is pretty lousy for the user experience.

Nothing really solid, unfortunately. I managed to get a super rudimentary version working by hooking into some of the navigation callbacks, but I pretty much had to write custom code for saving and restoring the nav state.

If you want to look at my code for an example the repository is up on GitHub on the restore-state branch. The most relevant file is app/save-restore.ts, it defines saveNavState() and restoreNavState() which do the heavy lifting. saveNavState() gets called each time the app’s state changes in a meaningful way. It walks up the nav stack and calls collectState() on each page. collectState() is a custom method that I write for each page that serializes all state to a simply javascript object. Once the state from every page has been collected, saveNavState() converts the state to JSON and saves it to disk. Conversely, restoreNavState() get’s called at startup and attempts to load the stored JSON string, parse it, and use that data to restore the nav stack. It’s all one big hack, but I suspect that a knowledgable Ionic developer could build a more robust library for doing the same basic thing.

Hope that helps!

1 Like

Here is a solution that works for me:

    saveNavStack() {
        this.stack = [];
        for(let i = 0; i < this.nav.length(); i++) {
            let view = this.nav.getByIndex(i);
            this.stack.push({
                page: view.componentType,
                params: view.data
            });
        }
    }

    restoreNavStack() {
        this.nav.setPages(this.stack);
    }
1 Like

I’ve been trying to use this code but it does not work as view.componentType no longer exists. I tried with view.component and view.component.name. Do you have updated code that works with the latest versions of Ionic/Angular?

(ionic v3) You can get the component’s constructor as follows:

const view = this.nav.getByIndex(i);
this.stack.push({
                page: view.data.component
            });