The realization of route and navigation in the development of flutter

Time:2020-6-28

If the basic unit that makes up the view element is the component, then the basic unit that makes up the application is the page. For applications with multiple pages, how to smoothly transition from one page to another is a problem that needs to be considered in the technical framework.

In front-end development, routing framework can be used to manage pages and their transitions. In Android, routing refers to an activity, in IOS, it refers to a viewcontroller. You can open a new route through startactivity or pushviewcontroller. In flutter, route management and navigation use the design ideas of front-end and client for reference, and need to use route and navigator for unified management.

Route is the abstract of the page, which is mainly responsible for creating the interface, receiving parameters and opening and closing the response navigator navigator. The navigator is used to maintain the route stack management. Route can be opened and pushed in, and route can be closed and pushed out. Of course, it can also replace a route in the stack. As an official route management component, navigator provides a series of methods to manage the route stack. The two most commonly used methods are push() and pop(). Their meanings are as follows.

  • Push(): to stack the given route. The return value is a future object, which is used to receive the return data when routing out of the stack.
  • Pop(): route the top of the stack out of the stack. The returned result is the data returned to the previous page when the page is closed.

In addition to the push() and pop() methods, navigator also provides many other practical methods, such as replace(), removeroute(), popuntil(), etc., which can be reasonably selected according to the use scenario.

According to whether the page identifier needs to be registered in advance, the route management in flutter can be divided into two types: basic route and named route.

  • Basic route: there is no need to register in advance, and the page instance needs to be constructed manually during page switching.
  • Named route: you need to register the page identifier in advance, and open the new route directly through the identifier during page switching.

Next, let’s focus on the basic route management and named route in flutter.

Basic routing

In the development of flutter, the use of basic routing is very similar to the way that native Android and IOS open new pages. To open a new page, you only need to create a MaterialPageRoute object instance, and then call it. Navigator.push () method can push the new page to the top of the routing stack. If you want to return to the previous page, you can call Navigator.pop () method.

Among them, materialpageroute is a route template, which defines the relevant configuration of route creation and transition animation of route switching. The configuration can realize the route switching animation with the same style as the platform page switching animation according to different platforms. The following is an example of page Jump using navigator, the code is as follows.

class FirstPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  Title: text ('first page '),
  ),
  body: Center(
  child: RaisedButton(
   Child: text ('jump to the second page '),
   onPressed: () => Navigator.push(context,
    MaterialPageRoute(builder: (context) => SecondPage()))),
  ),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  Title: text ('second page '),
  ),
  body: Center(
  child: RaisedButton(
   Child: text ('back to previous page '),
 onPressed: () => Navigator.pop(context)),
  ),
 );
 }
}

In the example above, we created two pages, each containing a button. When you click the button on the first page, you will navigate to the second page, and click the button on the second page to return to the first page. Run the above code, the effect is shown in the following figure.

You can see that the jump page uses Navigator.push () method, which can add a new route to the top of the stack of route objects managed by navigator. The material pageroute is used to create a new routing object. The material pageroute is a subclass of pageroute. It defines the relevant interface and properties of transition animation when creating and switching routes, and brings its own page switching animation. The entry animation of Android platform page is sliding up and fading out, and the exit is the opposite. The entry animation of IOS platform page is sliding in from the right, and the exit is the opposite.

Named route

The use of basic routing is relatively simple and flexible, which is suitable for the scenario with few pages in the application. When there are many pages in the application, if you use the basic routing method again, you need to manually create a materialpageroute instance every time you jump to a new page, and then call the push() method to open a new page. At this time, the management and jump of the page are confusing.

In order to avoid frequent creation of materialpageroute instances, flutter provides another way to simplify route management, named route. The so-called named route is to give the page an alias, and then use the page alias to open it, using this way to manage the route, making the route management more clear and intuitive.

To specify page switching by alias, you must first provide a page name mapping rule, i.e. routing table, to the application materialapp. The routing table is a map < string, widgetbuilder > structure, where key corresponds to the page name and value is the corresponding page, as shown below.

MaterialApp(
 ... // other configurations
 Routes: {// register routes
  'first':(context)=>FirstPage(),
  'second':(context)=>SecondPage(),
},
Initialroute: 'first', // initial route page
);

After registering the page in the routing table, you can use the Navigator.pushNamed Method () to open the page, as shown below.

Navigator.pushNamed (context, "second"); // second means page alias

However, since the registration and use of routes are identified by strings, this will cause a problem, that is, if a nonexistent route page is opened. To solve these problems, there is a general solution for mobile applications, that is, to jump to a unified error page. When registering the route table, flutter provides an unknownroute attribute, which is used to perform unified page Jump processing for unknown route identifiers, as shown below.

MaterialApp(
 …
routes:{},
 Onunknownroute: (routsettings setting) = > materialpageroute (Builder: (context) = > unknownpage()), // error route processing, return unknownpage
);

class UnknownPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
  Title: text ('wrong route '),
  ),
 );
 }
}

Route nesting

Sometimes, an application may have more than one navigator, but there may be multiple navigators. The behavior of nesting one navigator in another navigator is called routing nesting. Routing nesting is very common in mobile development. For example, in mobile development, it is often seen that the application home page has a bottom navigation bar, and each bottom navigation bar is nested with other pages. The effect is shown in the following figure.

To achieve the above example effect, you need to create a new bottom navigation bar, and then nest other sub routes from the bottom navigation bar. For the implementation of the bottom navigation bar, you can directly use the bottom NavigationBar attribute of the scaffold layout component, as shown below.

class MainPage extends StatefulWidget {
 @override
 State<StatefulWidget> createState() {
 return MainPageState();
 }
}

class MainPageState extends State<MainPage> {
 Int currentindex = 0; // bottom navigation bar index
 final List<Widget> children = [
 Homepage(), // home page
 Minepage(), // my
 ];

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: children[currentIndex],
  bottomNavigationBar: BottomNavigationBar(
  onTap: onTabTapped,
  currentIndex: currentIndex,
  items: [
   BottomNavigationBarItem(icon: Icon( Icons.home ), Title: text ('first page '),
   BottomNavigationBarItem(icon: Icon( Icons.person ), Title: text ('My '),
  ],
  ),
 );
 }

 void onTabTapped(int index) {
 setState(() {
  currentIndex = index;
 });
 }
}

Then, each bottom navigation bar will nest a sub route, and then sub route to manage the corresponding route page. In flutter, the navigator component is required to create a sub route, and the ongenerateroute property is required to intercept the sub route, as shown below.


class HomePage extends StatelessWidget {

 @override
 Widget build(BuildContext context) {
 return Navigator(
  initialRoute: 'first',
  onGenerateRoute: (RouteSettings settings) {
  WidgetBuilder builder;
  switch (settings.name) {
   case 'first':
   builder = (BuildContext context) => FirstPage();
   break;
   case 'second':
   builder = (BuildContext context) => SecondPage();
   break;
  }
  return new MaterialPageRoute(builder: builder, settings: settings);
  },
 );
 }
}

Run the above code, when clicking the button on the sub route page, the navigation bar at the bottom will not disappear, because the sub route is only valid in its own range. To jump to other sub route management pages, you need to register in the root navigator, which is the navigator inside materialapp.

Route parameters

In the development of mobile applications, the transfer of page parameters is also a common requirement. In order to meet the requirements of parameter transfer in the process of page Jump in different scenarios, the router provides a routing parameter mechanism, which can transfer parameters when the route is opened, and then obtain the parameters of page transfer through routsettings on the target page, as shown below.

Navigator.of(context).pushNamed("second ", arguments: " from first page");

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
//Get route parameters
 String msg = ModalRoute.of(context).settings.arguments as String; 
  …  //Data processing
 }
}

In addition, for some specific pages, the processing results of page processing need to be returned when they are closed. This is similar to the scenario where the startactivityforresult() method provided by Android listens to the target page to return processing results, and the flutter also provides a parameter mechanism for page return. Specifically, when using the push() method to open the target page, you can set the listening function when the target page is closed to obtain the return parameters. When the target page is closed to route, you can use the pop() method to return the parameters. For example, the following is the parameter value transfer and parameter value return between two pages. The code is as follows.

class FirstPage extends StatefulWidget {
 @override
 State<StatefulWidget> createState() {
 return FirstPageState();
 }
}

class FirstPageState extends State<FirstPage> {
 
String result = '';

 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: Center(
   child: Column(
  children: <Widget>[
   Text('from seconde page: ' + result, style: TextStyle(fontSize: 20)),
   RaisedButton(
    Child: text ('jump '),
    //Use then () to get the return parameters of the target page
    onPressed: () => Navigator.of(context)
     .pushNamed("second", arguments: "from first page")
     .then((msg) => setState(() => result = msg)))
  ],
  )),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {

 String msg = ModalRoute.of(context).settings.arguments as String;

 return Scaffold(
  body: Center(
   child: Column(children: [
   Text('from first screen: ' + msg, style: TextStyle(fontSize: 20)),
   RaisedButton(
    Child: text ('return '),
    onPressed: () => Navigator.pop(context, "from second page"))
   ]),
  ));
 }
}

Running the above code, you can see that when the second page is closed and returned to the first page, the first page will display the returned parameter values, and the final effect is as shown in the following figure.

MaterialPageRoute

In the process of using routing, the materialpageroute class will be used. Materialpageroute inherits from pageroute class, which is an abstract class, representing a modal route page occupying the whole screen space. It also defines the relevant interfaces and properties of transition animation during route construction and switching.

MaterialPageRoute It is a component provided by the material component library. It can realize the route switching animation with the same style as the platform page switching animation for different platforms: when the page is opened, the new page will slide from the right edge of the screen to the left until all the new pages are displayed on the screen, and the previous page will slide from the current screen to the left of the screen and disappear; when it is closed Page, on the contrary, the current page will slide out from the right side of the screen, while the previous page will slide in from the left side of the screen.

The meanings of the materialpageroute constructor and parameters are as follows:


MaterialPageRoute({
 @required this.builder,
 RouteSettings settings,
 this.maintainState = true,
 bool fullscreenDialog = false,
 }) 

Their specific meanings are as follows:

  • Builder: a widgetbuilder type callback function. Its function is to build the specific content of the routing page. The return value is a widget. We usually implement this callback to return an instance of the new route.
  • Settings: contains the configuration information of route, such as route name and initial route (first page).
  • Maintainstate: by default, when a new route is pushed, the original route will still be saved in memory. If you want to release all the resources occupied by the route when it is not used, you can set maintainstate to false.
  • Fullscreendialog: indicates whether the new routing page is a full screen modal dialog. In IOS, if fullscreendialog is true, the new page will slide in from the bottom of the screen (not horizontally).

summary

Flutter provides basic routing and named routing to manage the jump between pages. Among them, the basic route needs to manually create a page instance by itself Navigator.push To complete the page Jump, the named route needs to register the page identifier and page creation method in advance Navigator.pushNamed Pass in the identifier to jump the page.

For named routes, if we need to respond to bad route identifiers, we need to register unknownroute as well. In order to fine control routing switching, flutter provides a parameter mechanism of page opening and page closing. When creating a page and closing a target page, we can take out the corresponding parameters. As you can see, with regard to routing navigation, flutter integrates the features of Android, IOS and react, which is simple but powerful.

In large and medium-sized applications, named paths are often used to manage the switching between pages. The most important role of named route is to establish the mapping relationship between the string identifier and each page, so that each page is completely decoupled. The switching of pages in the application can be done only through a string identifier, which lays a good foundation for the later modularization.

In addition, nested routing and routing parameters are also the core content of routing framework. This article is just the basic knowledge of the route and navigation of the flutter. Later, it will introduce the route development and navigation of the flutter from the aspects of pushreplacementnamed, popandpushnamed, pushnamedandremoveuntil and popuntil, as well as the third-party navigation library and source code analysis.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.