Flutter Learning 4: Flutter Development Basics (3) Routing Management

Table of contents

0 Preface

1 Routing management

 1.1 MaterialPageRoute

1.2 Navigator

 1.2.1 Future push(BuildContext context, Route route)

1.2.2  bool pop(BuildContext context, [ result ])

1.2.3  Future pushNamed(BuildContext context, String routeName,{Object arguments})

1.3 Non-named route passing value

1.4 Named routing

 1.4.1 Routing table

1.4.2 Register routing table

1.4.3 Open a new routing page through the routing name

1.4.4 Named route parameter passing

1.4.5 Adapt non-named route value transfer 

1.5 Route generation hook

1.6 Summary


0 Preface

This article is a study and summary of the preface to the second edition | "Flutter in Practice·Second Edition" (flutterchina.club) .

1 Routing management

  • Route usually refers to page in mobile development, which has the same conceptual meaning as Route in single-page application in web development.
  • Route usually refers to an Activity in Android and a ViewController in iOS.
  • The so-called routing management is to manage how to jump between pages, which is usually also called navigation management.
  • Routing management in Flutter is similar to native development. Whether it is Android or iOS, navigation management will maintain a routing stack. The routing push operation corresponds to opening a new page, and the routing pop operation corresponds to the page closing operation. Routing management mainly refers to how to manage the routing stack.

 1.1 MaterialPageRoute

MaterialPageRouteInherited from PageRouteclass, PageRouteclass is an abstract class that represents a modal routing page that occupies the entire screen space. It also defines related interfaces and properties for transition animation during routing construction and switching. MaterialPageRoute It is a routing component provided by the Material component library. It can implement routing switching animations consistent with the platform page switching animation style for different platforms :

  • For Android, when a new page is opened, the new page will slide from the bottom of the screen to the top of the screen; when the page is closed, the current page will slide from the top of the screen to the bottom of the screen and then disappear, while the previous page will be displayed on the screen.
  • For iOS, when a page is opened, the new page will slide from the right edge of the screen to the left side of the screen until all the new pages are displayed on the screen, while the previous page will slide from the current screen to the left side of the screen and disappear; when When closing a page, the opposite is true. The current page will slide out from the right side of the screen, and the previous page will slide in from the left side of the screen.
  • If you want to customize the route switching animation, you can inherit PageRoute yourself to implement it.
MaterialPageRoute({
    /*
      用于构建路由页面的具体内容,返回值是一个新路由的widget实例。
    */
    WidgetBuilder builder, 
    /*
      包含路由的配置信息,如路由名称、是否初始路由(首页)。
    */
    RouteSettings settings,
    /*
      是否维护原路由内存状态,默认true, 即当入栈一个新路由时,原来的路由仍然会被保存在内存中。
      如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为 false
    */
    bool maintainState = true,
    /*
      表示新的路由页面是否是一个全屏的模态对话框,在 iOS 中,
      如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)
    */
    bool fullscreenDialog = false,
  })

1.2 Navigator

  • NavigatorIt is a routing management component that provides methods to open and exit the routing page .
  • NavigatorA stack is used to manage the set of active routes.
  • Usually the page currently displayed on the screen is the route at the top of the stack.

 1.2.1 Future push(BuildContext context, Route route)

Open the unnamed route page : push the given route onto the stack (i.e. open a new page). The return value is an Futureobject used to receive the return data when the new route is popped off the stack (i.e. closed).

1.2.2  bool pop(BuildContext context, [ result ])

Close the routing page : Pop the top route from the stack (that is, close the page currently displayed on the screen). The return value is a bool object. result The data returned to the previous page when the page is closed.

1.2.3  Future pushNamed(BuildContext context, String routeName,{Object arguments})

Open the named route page : push the given route onto the stack (i.e. open a new page). The return value is an Futureobject used to receive the return data when the new route is popped off the stack (i.e. closed).

1.3 Non-named route passing value

/*
  创建一个TipRoute路由,它接受一个提示文本参数,负责将传入它的文本显示在页面上,
  另外TipRoute中添加一个“返回”按钮,点击后在返回上一个路由的同时会带上一个返回参数
*/
class TipRoute extends StatelessWidget {
  TipRoute({
    Key key,
    required this.text,  // 接收一个text参数
  }) : super(key: key);
  final String text;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("提示"),
      ),
      body: Padding(
        padding: EdgeInsets.all(18),
        child: Center(
          child: Column(
            children: <Widget>[
              Text(text),
              ElevatedButton(
                onPressed: () => Navigator.pop(context, "我是返回值"),
                child: Text("返回"),
              )
            ],
          ),
        ),
      ),
    );
  }
}


/*
  打开新路由TipRoute的代码:
*/
class RouterTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () async {
          // 打开`TipRoute`,并等待返回结果
          var result = await Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) {
                return TipRoute(
                  // 路由参数
                  text: "我是提示xxxx",
                );
              },
            ),
          );
          //输出`TipRoute`路由返回结果
          print("路由返回值: $result");
        },
        child: Text("打开提示页"),
      ),
    );
  }
}

1.4 Named routing

"Named Route" is a route with a name

 1.4.1 Routing table

To use named routing, you must first provide and register a routing table (routing table) so that the application knows which name corresponds to which routing component.

Definition of routing table: It is a Map,

  • key is the name of the route, which is a string;
  • value is a builder callback function, used to generate the corresponding routing widget.
  • When opening a new route through the route name, the application will find the corresponding WidgetBuilder callback function in the routing table based on the route name, and then call the callback function to generate the route widget and return it.
Map<String, WidgetBuilder> routes;

1.4.2 Register routing table

In MaterialApp中, add routesattributes, register routing table

MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
    ... // 省略其他路由注册信息
  } ,
  home: MyHomePage(title: 'Flutter Demo Home Page'),
);


/* 将home页面也注册为命名路由 */
MaterialApp(
  title: 'Flutter Demo',
  initialRoute:"/", //名为"/"的路由作为应用的home(首页)
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
   "/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
  } 
);

1.4.3 Open a new routing page through the routing name

onPressed: () {
  //打开命名路由页面
  Navigator.pushNamed(context, "new_page");

  //打开非命名路由页面
  //Navigator.push(context,
  //  MaterialPageRoute(builder: (context) {
  //  return NewRoute();
  //}));  
},

1.4.4 Named route parameter passing

/*
  1.先注册一个路由:
*/ 
routes:{
   "new_page":(context) => EchoRoute(),
  } ,

/*
  2.在路由页通过RouteSetting对象获取路由参数:
*/
class EchoRoute extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    //获取路由参数  
    var args=ModalRoute.of(context).settings.arguments;
    //...省略无关代码
  }
}

/*
  3.在打开路由时传递参数
*/
Navigator.of(context).pushNamed("new_page", arguments: "hi");

1.4.5 Adapt non-named route value transfer 

In 1.3 Non-named routing by value , TipRoutea text parameter is accepted. If TipRoutethe routing page is registered in the routing table, how to TipRouteopen it through the routing name and implement parameter passing without changing the source code?

/*
  1.将TipRoute注册到路由表,同时传递text参数
*/
MaterialApp(
  routes: {
   "tip2": (context){
     return TipRoute(text: ModalRoute.of(context)!.settings.arguments.toString());
   },
 }, 
);

/*
  2.TipRoute源码,见【 1.3 非命名路由传值 】
*/

/*
  3.在打开路由时传递参数值
*/
Navigator.of(context).pushNamed("tip2", arguments: "你好吗");

1.5 Route generation hook

  • The route generation hook refers to the properties MaterialAppinonGenerateRoute
  • onGenerateRoute Only takes effect on named routes
  • onGenerateRoute It may be called when opening a named route: when calling to open a Navigator.pushNamed(...)named route, if the specified route name has been registered in the routing table, the function in the routing table will be called builderto generate the routing component; if it is not registered in the routing table, it will Will be called onGenerateRouteto generate routes.
  • onGenerateRoute You can perform more detailed operations on routing and jump to different pages according to different situations. Permission control can also be performed.
  • onGenerateRoute Examples of applicable scenarios: Suppose we want to develop an e-commerce App. When users are not logged in, they can view store, product and other information, but transaction records, shopping carts, user personal information and other pages need to be logged in before they can be viewed.
MaterialApp(
  ... //省略无关代码
  onGenerateRoute:(RouteSettings settings){
      //返回一个Route<dynamic>
	  return MaterialPageRoute(builder: (context){
		   String routeName = settings.name;
       /*
          如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,引导用户登录;
          其他情况则正常打开路由。
       */ 
     }
   );
  }
);

1.6 Summary

 In actual development, it is recommended to use named routing management, which will bring the following benefits:

  1. The semantics are clearer.
  2. The code is easier to maintain; if you use anonymous routing, you must Navigator.pushcreate a new routing page where it is called. This not only requires importing the dart file of the new routing page, but also such code will be very scattered.
  3. You can onGenerateRoutedo some global routing jump pre-processing logic.

navigatorObserversThere are also onUnknownRoutetwo callback attributes in the routing MaterialApp :

  • navigatorObserversCan monitor all routing jump actions
  • onUnknownRouteCalled when opening a named route that does not exist

Guess you like

Origin blog.csdn.net/D_lunar/article/details/131416195
Recommended