This article is part of a series aiming at making you a master of Navigator 2.0 while showing you that it is not as hard as people think. The other articles of this series are:
- Flutter Navigator 2.0: 101 for mobile dev: Where to start if you have no idea what navigator 2.0 is.
- Flutter Navigator 2.0 for mobile dev: Nested navigators basics: How to nest the navigators, and the fix needed to avoid that they ruin your animations
- Flutter Navigator 2.0 for mobile dev: Transitions: How to implement Hero or Page route transitions with navigator 2.0
- Flutter Navigator 2.0 for mobile dev: Bloc state management integration: How to use navigator 2.0 and the bloc library
- Flutter Navigator 2.0 for web dev: Url handling: The basics of URL handling.
- Flutter web: URL handling made simple with simple_url_handler: How to use the simple_url_handler package to manage the URL in flutter web easily.
Navigator 2.0 received some negative feedback when it came out. However, today we will see how:
- Routing is not as hard as it looks.
- Url handling is made very easy by the package simple_url_handler
The app we will create
We will need 3 main widgets and 2 routers.
The app state
The state of the app will be stored in a
ChangeNotifier provided by a
ChangeNotifierProvider at the top of the app. Here is the app state class:
Three main attributes describe this class:
selectedBottomNavigationBarIndex: 0 is the profile, and 1 is the settings
redirectFromis set when the user tries to access
settingswhile not being allowed to. It hosts a
InAppPageswhich is either
isAuthenticatedwhich is self-explanatory. The interesting part is that it is a setter method. Indeed when authenticating (i.e., setting
isAuthenticatedto true) we check if
redirectedFromhas a value and if so, change
As always with navigator 2.0, we create a
Router widget, which will contain our
RouterDelegate (which is basically its child).
We also create a
RootBackButtonDispatcher because we cant to handle the
AppBar back button.
In the build method, we create a Navigator (to which we give a global key for page animations). The pages are
MaterialPages containing either the
AuthenticationWidget or the
NestedRouterWidget. Note how we declarative decide if we want to show the
NestedRouterWidget with the
isAuthenticated boolean from our app state.
In the onPop method, we set
isAuthenticated to false if we pop on the
AuthenticationWidget. This happens when we press the
AppBar back button, for example.
The popRoute method is triggered if we want to pop the
AuthenticationWidget, in that case, we stop the application gracefully with the move_to_background package.
Note that we use
obeservers: [HeroController()] because we need it to avoid breaking hero animations in the nested navigator. Since
SimpleUrlHandler will create a navigator, this is a nested navigator, so we add this.
This nested delegate is pretty much the same as the authentication one. Note how easy it is to nest navigator, nothing special: nest them.
We create a
BottomNavigationBar on top of our navigator so that it is shared between the two pages, and inside the navigator, we choose which Widget to display with the
Also, note how we return false in the
onPopPage method. This is because we handle the pop in the
AuthenticationRouterDelegate. Since we took priority in line 16, a pop event will first be triggered here, and then, if we return false, the next
onPopPage event will be triggered (so in our case, the
Concerning the URL it will be handled as follow:
/profilewhen the user is on the
/settingswhen the user is on the
/loginwhen the user is on the
/login#profilewhen the user tries to access
/profilebut is not authenticated
/login#settingswhen the user tries to access
/settingsbut is not authenticated
This can be easily achieved thanks to the simple_url_handler package.
The first interesting part is happening line 21–22. Indeed, we add a listener to the app state, which will call
SimpleUrlNotifier.of(context).notify any time the app state changes.
Then we must provide
appStateToUrl to the
urlToAppState is called whenever the url is typed manually or the forward/backward button is pressed. When it is called, we parse the route location and modify our app state accordingly. Note that if the
appState is updated,
appStateToUrl is called thanks to what we just saw. So any redirection will update the url. Also, note that if that state can not be changed to a valid one, we
SimpleUrlNotifier.of(context).notify() to update the url back to a valid one.
appStateToUrl is called when
SimpleUrlNotifier.of(context).notify() is called or when the
SimpleUrlHandler is built. Here we use our
AppState class to determine what should be the corresponding url.
Try it yourself
You can find the code for this app on github. Play around with the code, and you will soon realize that navigator 2.0 is a beauty.