-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[go_router] Add support for preloading branches of StatefulShellRoute (revised solution) #6467
base: main
Are you sure you want to change the base?
Conversation
I know I have been slacking off at this pr. I am sorry about this. My schedule is quite tight after I came back from vacation. This is still under my radar. I will try find time review this pr within 2 weeks |
No worries @chunhtai, I completely understand, have had far too much on my plate myself the last year 😅 |
return true; | ||
}); | ||
|
||
final Widget navigator = widget.shellRouteContext.navigatorBuilder( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might want to null check match here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, will update this.
RouteMatchList matchList, | ||
List<NavigatorObserver>? observers, | ||
String? restorationScopeId); | ||
// typedef NavigatorBuilder = Widget Function( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like this commented code can be removed
@@ -60,6 60,9 @@ class NestedTabNavigationExampleApp extends StatelessWidget { | |||
], | |||
), | |||
], | |||
// To enable preloading of the initial locations of branches, pass | |||
// 'true' for the parameter preload. | |||
// preload: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd find it clearer if the last line was uncommented as preload: false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may be right, I'll consider this.
/// *Note:* The primary purpose of branch preloading is to enhance the user | ||
/// experience when switching branches, which might for instance involve | ||
/// preparing the UI for animated transitions etc. Care must be taken to | ||
/// **keep the preloading to an absolute minimum** to avoid any unnecessary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The position here is overly dramatic imo. I'd change
Care must be taken to **keep the preloading to an absolute minimum** to avoid any unnecessary resource use.
into
Preloading involves resource usage for elements that are not displayed, as such this should be used sparingly.
or something like that.
Personally I'm going to use that for every top level branch, which I have 5 of. That's not the absolute minimum. Anyway, I just find the wording too strong and might scare some people from using an otherwise useful feature. People can benchmark the effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great feedback. This wording was actually due to some rather lengthy discussion in the original PR around the potential negative aspects of preloading, as I recall it. There are always dangers of premature/unnecessary optimisation when exposing these kinds of APIs, so some level of cautionary language is certainly justified. But maybe it can be dialed back a bit.
Any updates on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, just some comments
@@ -996,6 1011,7 @@ class StatefulShellBranch { | |||
this.initialLocation, | |||
this.restorationScopeId, | |||
this.observers, | |||
this.preload = false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we check for initiallocation is set if preload is true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think that should be necessary, as it will fall back on the defaultRoute
if initialLocation
isn't provided.
@@ -1032,6 1048,21 @@ class StatefulShellBranch { | |||
/// The observers parameter is used by the [Navigator] built for this branch. | |||
final List<NavigatorObserver>? observers; | |||
|
|||
/// Whether this route branch should be loaded only when navigating to it for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you inverse the statement? from reading it, it seem to not preload when this property is true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, forgot to change that. How about this: "Whether this route branch should be eagerly loaded when navigating to it for the first time..."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's also confusing, it's not preloading when accessing the branch for the first time but when accessing the shell.
"Whether this "StatefulShellBranch" should be preloaded once the "StatefulShellRoute" has been accessed."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, but of course, how about this:
"Whether this route branch should be eagerly loaded when navigating to the associated StatefulShellRoute for the first time."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's much better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes sounds good to me, can you reflect that to the doc string?
@@ -1255,8 1291,39 @@ class StatefulNavigationShellState extends State<StatefulNavigationShell> | |||
final bool locationChanged = | |||
previousBranchLocation != currentBranchLocation; | |||
if (locationChanged || !hasExistingNavigator) { | |||
_branchNavigators[branch.navigatorKey] = shellRouteContext | |||
.navigatorBuilder(branch.observers, branch.restorationScopeId); | |||
_branchNavigators[branch.navigatorKey] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just realized somewhere in this method should probably remove entries in _branchNavigators the are no longer in the StatefulShellRoute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, that is definitely necessary to do now. Will have a look at it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chuntai, I added a fix for removing old entries, but when attempting to write a test case, I ran into issues with duplicate GlobalKeys (_shellStateKey) when updating the dynamic RoutingConfig. Or - I should be clear - at first the test case worked, but not because of the code I added, but instead because the entire StatefulShellRoute was replaced/reloaded. But when I added the possibility to set the GlobalKey<StatefulNavigationShellState> _shellStateKey
to maintain state, I started to get this error.
When trying to troubleshoot it, I started to wonder whether dynamic RoutingConfig full supports ShellRoutes, at least with state. Added some test cases to test this, and it seems simple StatefulWidgets in a simple routing scenario works, but when adding a (regular) ShellRoute with a stateful shell I also get and issue with duplicate GlobalKeys.
Not sure if I just missed something, but I anyway added a gist with the test cases here: https://gist.github.com/tolo/922fd838cdea30b17121533b0012eda4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you file an issue for it? looks like a bug
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the fix in this pr already?
What's the status here ? It seems like you said that you have a test locally that's failing but it's unrelated to the changes here ? |
Yes, @chunhtai, have you had a chance to too look at my comment above (#6467 (comment))? The issue is however only with testing if obsolete branch navigators are removed (which is done dynamic RoutingConfig), so possibly this could be moved to a separate issue/PR. And another issue should probably be opened for fixing the support for dynamic RoutingConfig for (stateful) shell routes. What do you think @chunhtai? |
will take a look this week |
routes: <RouteBase>[ | ||
StatefulShellRoute( | ||
StatefulShellRoute.indexedStack( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why changing this example? In stead of adding more complexity to this example, we should probably create a new example that target specific feature
@@ -1032,6 1048,21 @@ class StatefulShellBranch { | |||
/// The observers parameter is used by the [Navigator] built for this branch. | |||
final List<NavigatorObserver>? observers; | |||
|
|||
/// Whether this route branch should be loaded only when navigating to it for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes sounds good to me, can you reflect that to the doc string?
@@ -1255,8 1291,39 @@ class StatefulNavigationShellState extends State<StatefulNavigationShell> | |||
final bool locationChanged = | |||
previousBranchLocation != currentBranchLocation; | |||
if (locationChanged || !hasExistingNavigator) { | |||
_branchNavigators[branch.navigatorKey] = shellRouteContext | |||
.navigatorBuilder(branch.observers, branch.restorationScopeId); | |||
_branchNavigators[branch.navigatorKey] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you file an issue for it? looks like a bug
@@ -1255,8 1291,39 @@ class StatefulNavigationShellState extends State<StatefulNavigationShell> | |||
final bool locationChanged = | |||
previousBranchLocation != currentBranchLocation; | |||
if (locationChanged || !hasExistingNavigator) { | |||
_branchNavigators[branch.navigatorKey] = shellRouteContext | |||
.navigatorBuilder(branch.observers, branch.restorationScopeId); | |||
_branchNavigators[branch.navigatorKey] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the fix in this pr already?
Adds support for preloading branches in a
StatefulShellRoute
. This functionality was initially part of an early implementation of #2650, however it was decided to implement this in a separate PR. The current implementation is a rewrite of the original implementation to better fit the final version ofStatefulShellRoute
(and go_router in general).NOTE: this is a revised version of the initial solution (see #4251), containing a substantially simpler implementation made possible thanks to recent refactoring in go_router.
This fixes issue flutter/flutter#127804.
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.