Skip to content

Conversation

@goderbauer
Copy link
Member

@goderbauer goderbauer commented Sep 11, 2020

Description

WidgetsApp, MaterialApp, and CupertinoApp now take a restoration ID to enable state restoration for the app (and the Navigator build by those widgets).

The navigator now takes a restoration id to restore its state by recreating the current history stack of Routes during state restoration and by restoring the internal state of those Routes. However, not all Routes on the stack can be restored:

  • Page-based routes restore a restoration ID is provided to them.
  • Routes added with the existing imperative API (push, pushNamed, and friends) can never restore their state.
  • A Route added with the newly added restorable imperative API (restorablePush, restorablePushNamed, and all other imperative methods with "restorable" in their name) restores its state if all routes below it up to and including the first Page-based route below it are restored. If there is no Page-based route below it, it only restores its state if all routes below it restore theirs.

If a Route is deemed restorable by the Navigator, they will insert their own RestorationScope into the tree that the widgets in the route can use to restore their own state.

Related Issues

#62916

Tests

I added the following tests:

Restoration tests for the Navigator and the newly added restorable API.

Checklist

Before you create this PR, confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Did any tests fail when you ran them? Please read Handling breaking changes.

@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. work in progress; do not review labels Sep 11, 2020
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a line above this, like, "The identifier to use when enabling state restoration for the navigator." or whatever, missing. (The first line of docs should be a noun phrase.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why "nav"? Why not "n" or "navigator" or "\0x01" or "$Navigator" or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Any of those are valid as long as they are unique within the surrounding restoration scope. Here, the navigator is the only thing in this scope. Children (the individual routes) have their own scope.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why "nav" specifically?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, the analyzer didn't warn about the missing docs here. Filed https://github.com/dart-lang/linter/issues/2238.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throughout -> during

throughout implies it happening continually, during refers to a particular case of it happening

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...transitioning off screen, which triggers a notification on this field" or some such. (Right now, you say "as an example" but don't actually then say why what you describe is an example of the previous sentence)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"in their names"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in "navigator"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this mention the default id that WidgetsApp uses?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WidgetsApp doesn't use a default id.

It internally specifies an ID for the Navigator it creates. However, that's an implementation detail that's not exposed to the public.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put some punctuation between the prefix and the id (or use something other than letters), to avoid the risk of someone being offended if they use the id "rick" or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, but good point. Added a "+".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

declare this before first use

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"endtempalte" is a typo

might be good to have some sample code here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the restorable* methods should be mentioned in their corresponding non-restorable version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should do that in this PR

@Hixie
Copy link
Contributor

Hixie commented Sep 11, 2020

Overall LGTM. Some minor comments.

@goderbauer goderbauer changed the title Make Navigator restorable Make Navigator restorable (inkl. WidgetsApp, MaterialApp, CupertinoApp) Sep 22, 2020
@goderbauer goderbauer force-pushed the restorableNavigator branch 2 times, most recently from 4be8695 to 47d24b6 Compare September 23, 2020 21:07
@goderbauer goderbauer marked this pull request as ready for review September 23, 2020 23:56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does user have chance to use the RootRestorationScope? isn't this only used by the navigator widget or router widget?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rephrased.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be nullable String?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and other places

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time the PR was created, this file had not been migrated to NNBD, so this was correct. I am going to rebase this to the latest master, though, and then it will have to be nullable, yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other unmigrated files it cannot be marked as nullable just yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't the restorablePush just return the restorable future? if we asked user to provide their own restorationid to the route, I think we can probably restore this future with the logic similar to the _hookOntoRouteFuture?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After state restoration, how would the entity that pushed the route get access to the restorableRouteFuture again that was returned when the route was initially pushed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this because there is no way to restore the future chain unless all the call back are static functions? Restore the route future is possible I think? but then caller will have to reattach their future chain again.

Copy link
Member Author

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All comments addressed. PTAL

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time the PR was created, this file had not been migrated to NNBD, so this was correct. I am going to rebase this to the latest master, though, and then it will have to be nullable, yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rephrased.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other unmigrated files it cannot be marked as nullable just yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After state restoration, how would the entity that pushed the route get access to the restorableRouteFuture again that was returned when the route was initially pushed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's the same API as pushReplacementNamed, does it need to be different?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example, don't we need to be doing something with the return value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You only have to do something with the return value if you want to get access to the return value of the route or the route object itself. If you don't care about any of this, the usage is exactly the same. See also the flutter.widgets.navigator.restorablePushNamed.returnValue docs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also added some clearer language around this to the doc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this supposed to return String?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never mind i didn't see the @macro flutter.widgets.navigator.restorablePushNamed.returnValue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a String I could make this one return an opaque RouteId object, if that sounds better...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be before the sample

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to discard the return value

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which is fine, see new and improved doc on return value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this also ignores the return value

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which is fine, see new and improved doc on return value.

Copy link
Contributor

@Hixie Hixie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM modulo some docs questions

Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the restoration framework sends update if the platform is web?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The web embedder currently does not turn on restoration.

@goderbauer goderbauer force-pushed the restorableNavigator branch from b299b10 to 9f0856a Compare October 1, 2020 20:22
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Mac framework_tests has failed. Please fix the issues identified (or deflake) before re-applying this label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants