Navigator 组件支持通过使用通用标识符从应用程序的任何地方导航到特定路由。在某些情况下,你可能还希望能够传递参数给特定路由。例如,你希望导航到 /user 路由并携带上用户信息。

在 Flutter 中,你能通过提供额外的 argumentsNavigator.pushNamed 方法方便地完成这个任务。通过使用 ModalRoute.of 方法或 MaterialAppCupertinoApp 构造器中的 onGenerateRoute 来获取参数。

这个章节讲解的是如何给特定路由传递参数并使用 ModelRoute.ofonGenerateRoute 来读取参数。

步骤

  • 定义需要传递的参数

  • 创建组件来获取参数

  • 把组件注册到路由表中

  • 导航到组件

1. 定义需要传递的参数

首先,定义需要传递给新路由的参数。在这个示例中,传递了两个数据: 页面的标题 title 和内容 message

创建包含 title 和 message 字段的实体类来同时传递这两个数据。

  1. // You can pass any object to the arguments parameter. In this example, create a
  2. // class that contains both a customizable title and message.
  3. class ScreenArguments {
  4. final String title;
  5. final String message;
  6. ScreenArguments(this.title, this.message);
  7. }

2. 创建组件来获取参数

接着,创建组件,从 ScreenArguments 提取 titlemessage 参数并展示。为了访问 ScreenArguments,可以使用 ModalRoute.of 方法。这个方法返回的是当前路由及其携带的参数。

  1. // A Widget that extracts the necessary arguments from the ModalRoute.
  2. class ExtractArgumentsScreen extends StatelessWidget {
  3. static const routeName = '/extractArguments';
  4. @override
  5. Widget build(BuildContext context) {
  6. // Extract the arguments from the current ModalRoute settings and cast
  7. // them as ScreenArguments.
  8. final ScreenArguments args = ModalRoute.of(context).settings.arguments;
  9. return Scaffold(
  10. appBar: AppBar(
  11. title: Text(args.title),
  12. ),
  13. body: Center(
  14. child: Text(args.message),
  15. ),
  16. );
  17. }
  18. }

3. 把组件注册到路由表中

然后,在 MaterialApp 的路由表 routes 中增加一个入口。路由表 routes 会根据路由的名称来决定需要创建哪个路由。

  1. MaterialApp(
  2. routes: {
  3. ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
  4. },
  5. );

4. 导航到组件

最后,在用户点击按钮后导航到 ExtractArgumentsScreen。在 Navigator.pushNamed 方法的 arguments 属性里提供需要传递的参数。随后,ExtractArgumentsScreen 就可以从参数中提取 titlemessage

  1. // A button that navigates to a named route that. The named route
  2. // extracts the arguments by itself.
  3. RaisedButton(
  4. child: Text("Navigate to screen that extracts arguments"),
  5. onPressed: () {
  6. // When the user taps the button, navigate to the specific rout
  7. // and provide the arguments as part of the RouteSettings.
  8. Navigator.pushNamed(
  9. context,
  10. ExtractArgumentsScreen.routeName,
  11. arguments: ScreenArguments(
  12. 'Extract Arguments Screen',
  13. 'This message is extracted in the build method.',
  14. ),
  15. );
  16. },
  17. );

此外,还可以使用 onGenerateRoute 提取参数

除了直接从组件里提取参数,你也可以通过 onGenerateRoute 函数提取参数,然后把参数传递给组件。

onGenerateRoute 函数会基于给定的 RouteSettings 来创建正确的路由。

  1. MaterialApp(
  2. // Provide a function to handle named routes. Use this function to
  3. // identify the named route being pushed and create the correct
  4. // Screen.
  5. onGenerateRoute: (settings) {
  6. // If you push the PassArguments route
  7. if (settings.name == PassArgumentsScreen.routeName) {
  8. // Cast the arguments to the correct type: ScreenArguments.
  9. final ScreenArguments args = settings.arguments;
  10. // Then, extract the required data from the arguments and
  11. // pass the data to the correct screen.
  12. return MaterialPageRoute(
  13. builder: (context) {
  14. return PassArgumentsScreen(
  15. title: args.title,
  16. message: args.message,
  17. );
  18. },
  19. );
  20. }
  21. },
  22. );

完整示例

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. // Provide a function to handle named routes. Use this function to
  8. // identify the named route being pushed and create the correct
  9. // Screen.
  10. onGenerateRoute: (settings) {
  11. // If you push the PassArguments route
  12. if (settings.name == PassArgumentsScreen.routeName) {
  13. // Cast the arguments to the correct type: ScreenArguments.
  14. final ScreenArguments args = settings.arguments;
  15. // Then, extract the required data from the arguments and
  16. // pass the data to the correct screen.
  17. return MaterialPageRoute(
  18. builder: (context) {
  19. return PassArgumentsScreen(
  20. title: args.title,
  21. message: args.message,
  22. );
  23. },
  24. );
  25. }
  26. },
  27. title: 'Navigation with Arguments',
  28. home: HomeScreen(),
  29. );
  30. }
  31. }
  32. class HomeScreen extends StatelessWidget {
  33. @override
  34. Widget build(BuildContext context) {
  35. return Scaffold(
  36. appBar: AppBar(
  37. title: Text('Home Screen'),
  38. ),
  39. body: Center(
  40. child: Column(
  41. mainAxisAlignment: MainAxisAlignment.center,
  42. children: <Widget>[
  43. // A button that navigates to a named route that. The named route
  44. // extracts the arguments by itself.
  45. RaisedButton(
  46. child: Text("Navigate to screen that extracts arguments"),
  47. onPressed: () {
  48. // When the user taps the button, navigate to the specific route
  49. // and provide the arguments as part of the RouteSettings.
  50. Navigator.push(
  51. context,
  52. MaterialPageRoute(
  53. builder: (context) => ExtractArgumentsScreen(),
  54. // Pass the arguments as part of the RouteSettings. The
  55. // ExtractArgumentScreen reads the arguments from these
  56. // settings.
  57. settings: RouteSettings(
  58. arguments: ScreenArguments(
  59. 'Extract Arguments Screen',
  60. 'This message is extracted in the build method.',
  61. ),
  62. ),
  63. ),
  64. );
  65. },
  66. ),
  67. // A button that navigates to a named route. For this route, extract
  68. // the arguments in the onGenerateRoute function and pass them
  69. // to the screen.
  70. RaisedButton(
  71. child: Text("Navigate to a named that accepts arguments"),
  72. onPressed: () {
  73. // When the user taps the button, navigate to a named route
  74. // and provide the arguments as an optional parameter.
  75. Navigator.pushNamed(
  76. context,
  77. PassArgumentsScreen.routeName,
  78. arguments: ScreenArguments(
  79. 'Accept Arguments Screen',
  80. 'This message is extracted in the onGenerateRoute function.',
  81. ),
  82. );
  83. },
  84. ),
  85. ],
  86. ),
  87. ),
  88. );
  89. }
  90. }
  91. // A Widget that extracts the necessary arguments from the ModalRoute.
  92. class ExtractArgumentsScreen extends StatelessWidget {
  93. static const routeName = '/extractArguments';
  94. @override
  95. Widget build(BuildContext context) {
  96. // Extract the arguments from the current ModalRoute settings and cast
  97. // them as ScreenArguments.
  98. final ScreenArguments args = ModalRoute.of(context).settings.arguments;
  99. return Scaffold(
  100. appBar: AppBar(
  101. title: Text(args.title),
  102. ),
  103. body: Center(
  104. child: Text(args.message),
  105. ),
  106. );
  107. }
  108. }
  109. // A Widget that accepts the necessary arguments via the constructor.
  110. class PassArgumentsScreen extends StatelessWidget {
  111. static const routeName = '/passArguments';
  112. final String title;
  113. final String message;
  114. // This Widget accepts the arguments as constructor parameters. It does not
  115. // extract the arguments from the ModalRoute.
  116. //
  117. // The arguments are extracted by the onGenerateRoute function provided to the
  118. // MaterialApp widget.
  119. const PassArgumentsScreen({
  120. Key key,
  121. @required this.title,
  122. @required this.message,
  123. }) : super(key: key);
  124. @override
  125. Widget build(BuildContext context) {
  126. return Scaffold(
  127. appBar: AppBar(
  128. title: Text(title),
  129. ),
  130. body: Center(
  131. child: Text(message),
  132. ),
  133. );
  134. }
  135. }
  136. // You can pass any object to the arguments parameter. In this example, create a
  137. // class that contains both a customizable title and message.
  138. class ScreenArguments {
  139. final String title;
  140. final String message;
  141. ScreenArguments(this.title, this.message);
  142. }

Demonstrates navigating to different routes with arguments