An App is composed of many pages, we need to click to jump to different pages, rather than just click the Set IndexedStack property with BottomNavigationBarItem to switch pages. Usually we manage the jump uniformly through the route.

What is routing

There is a routing mapping table that finds the page to jump to by a unique identifier. There are two main classes for Route management in Flutter: Route and Navigator

Route

To be routable, a page must be wrapped as a Route. MaterialPageRoute, a subclass of PageRoute, represents a modal routing page and defines interfaces and properties of transition animation during route construction and switching. MaterialPageRoute is a component provided by the Material component library. It can realize the route switching animation consistent with the style of platform page switching animation for different platforms.

  • On iOS, opening a page slides from the right to the left of the screen and disappears from left to right when you return
  • On Android, opening a page slides from the bottom of the screen to the top of the screen, and closing the page slides from the top to the bottom and disappears

The inheritance relationship looks like this

MaterialPageRoute->PageRoute->ModalRoute->TransitionRoute->OverlayRoute->Route
Copy the code

Navigator

Navigator: Widget that manages all routes by stack, usually the page on the current screen is the Route at the top of the stack.

Component routing

Route jump, passing in a route object route. This method adds the new route to the top of the stack of the route objects managed by the Navigator

Navigator.of(context).push(route)
Copy the code

Return to the previous page, where you can return with [T? Result] as an argument, and exit to move the routing object off the stack

Navigator.of(context).pop()
Copy the code

The sample code

child: ElevatedButton( onPressed: (){ Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){ return PageDetail(); })); }, child: Text(' enter details '),),Copy the code
child: ElevatedButton( onPressed: (){ Navigator.of(context).pop(); }, child: Text(' return '),),Copy the code

Navigation-back interception

In order to prevent users from accidentally touching the back button and causing the App to exit, many apps block the button when users click the back button, and then make some anti-wrong touch judgment. For example, when users click the back button twice in a certain period of time, the user will be considered to exit (but not by mistake). Return button interception can be implemented in Flutter via WillPopScope. Let’s look at the WillPopScope default constructor:

const WillPopScope({
  ...
  required WillPopCallback onWillPop,
  required Widget child
})
Copy the code

OnWillPop is a callback function that is called when the user clicks the back button (both the navigation back button and the Android physical back button). This callback needs to return a Future object. If the final value of the Future returned is false, the current route is not removed from the stack (it is not returned). When the final value is true, the current route exits the stack. We need to provide this callback to decide whether to exit or not.

@override Widget build(BuildContext context) { WillPopScope( onWillPop: onWillPop, child: Scaffold()) onWillPop:() {print(' exiting this interface '); //return Future.value(false); // Prevent exit return future. value(true); // Exit}}Copy the code

After routing

Basic routing is relatively simple to use, but it is not suitable for a large number of pages in the scene, each jump to a new page to create a new route, so it is more confusing. The named route is to give each page an alias, through the alias can be found to open the page, so that management is relatively clear and convenient.

To implement page switching by alias, a page name mapping rule provided by The MaterialApp, namely the routing table, is required. The routing table is a Map structure where key is the alias of the page and value is the corresponding page.

The four key properties used by Navigator

  • InitialRoute: the initialRoute, that is, enter the APP, the default page
  • OnGenerateRoute: Route interceptor, used when special processing is required for a route
  • OnUnknownRoute: An error page is created by default if the page cannot be found
  • Routes: During route redirection, the sub-routes in the route set are matched. If a match is found, the sub-routes are adjusted to the specified page

The sample code

Return MaterialApp(// Routes: {'/': (context) => HomePage(), 'basic': (context) => BasicPage(), 'form_main': (context) => FormMainPage(), 'nav': (context) => NavigationMainPage(),}, 'hoemPage', // onUnknownRoute: (RouteSettings routerName) {print(" $routername.name "); return new MaterialPageRoute(builder: (context) { return ErrorPage(); }); }}Copy the code

Routing hooks

The MaterialApp has an onGenerateRoute property when called Navigator. PushNamed (…) When the named route is enabled, if the specified route name is registered in the routing table, the builder function in the routing table is called to generate routing components. If there is no registration in the routing table, onGenerateRoute is called to generate the route. You can then use the RouteSettings parameter in the route to determine if special treatment is needed, such as opening a route that requires permission to determine the jump.

onGenerateRoute: (settings) { if (settings.name == "login") { return MaterialPageRoute( builder: (context) { return LoginPage(settings.arguments); }); } return null; },Copy the code

How does Navigator pass parameters and return values

  1. Once registered, you can passNavigator.pushNamed()I’ve opened the page
Navigator.pushNamed(context, "basic"); // Jump Navigator. PushNamed (context, "basic", arguments: 'parameters to pass ');Copy the code
  1. Gets the parameters passed
Widget build(BuildContext context) { // 1. Final args= modalRoute. of(context)! .settings.arguments; }Copy the code
  1. The return page is throughNavigator.pop
Navigator.pop(context); Navigator.pop(context, "return value ");Copy the code
  1. When receiving returned data, modify the jump method
Navigator. PushNamed (context, 'basic'). Then ((value) => print(' received data ${value}');Copy the code
  1. Return to theSpecified pageIs through theNavigator.popUntil
PopUntil (context, modalroute.withname (' route '));Copy the code

Navigator’s various jumps

  • pushAndRemoveUntil: Jumps to a new page and deletes all pages between the new page and the bottom page
  • pushReplacement: A new page replaces the current page. You only need to create a new page and destroy the current page
  • pushReplacementNamed: the new page replaces the current page, just routing, named routing, current page destruction
  • popUntil: Returns to the specified page, and other pages are destroyed
  • popAndPushNamed: Exits the current page and a new page is displayed
  • canPop: Checks whether the current page can be removed from the stack, false if there is only one page in the stack, and true otherwise
  • maybePop: Check whether the current route is at the bottom of the stack. If not, exit

In normal use, Routes and onGenerateRoute can be separately extracted into a class, so that later maintenance is more clear and easy to modify.

The most important role of named routing is to establish the mapping relationship between string identifiers and each page, so that each page is completely decoupled, and the application of internal page switching only needs a string identifier can be done, which lays a good foundation for later modularization.

Tripartite plugin fluro

Fluro is an excellent Flutter enterprise routing framework. The use of Fluro is a little more complex than the official routing framework, but it is ideal for medium to large projects. Because it has the advantages of clear hierarchy, organization, convenient expansion, and overall route management. Fluro’s Github link: github.com/lukepighett…