【发布时间】:2020-05-06 09:40:31
【问题描述】:
onGenerateRoute 和 Flutter 中的路由有什么好处或用例。
在MaterialApp 内第一页的我的应用程序中,我们可以为我们的应用程序定义路由,就像我们可以使用onGenerateRoute 定义的一样。
两者都用于 NamedRoute。
我不确定,什么场景需要使用路由,什么场景需要使用onGenerateRoute?
【问题讨论】:
onGenerateRoute 和 Flutter 中的路由有什么好处或用例。
在MaterialApp 内第一页的我的应用程序中,我们可以为我们的应用程序定义路由,就像我们可以使用onGenerateRoute 定义的一样。
两者都用于 NamedRoute。
我不确定,什么场景需要使用路由,什么场景需要使用onGenerateRoute?
【问题讨论】:
没有错误,只是问题报告者使用不当。 这是因为他没有将设置对象传递给 onGenerateRoute 方法返回的新 MaterialPageRoute(请参阅问题的最终 cmets)。 [...]
没有深入研究任何细节,这两个属性做同样的事情,但正如@Alireza 所说,routes 首先被检查。
此外,使用onGenerateRoute 可以让您在推送新路由(页面)之前添加自定义业务逻辑。例如,如果你想做一些初始化。
使用 Navigator.pushNamed 推送命名路由时,路由名称 在此地图中查找。如果名称存在,则关联的 WidgetBuilder 用于构造一个 MaterialPageRoute 执行 适当的过渡,包括英雄动画,到新的 路线。
当应用导航到一个命名的路由生成器回调 路线。 ... 如果路由不包含请求的路由,则使用它。
重要提示:
您真正想知道的是onGenerateRoute 属性中的known bug。
问题是,如果您使用onGenerateRoute 创建命名路由,您将无法从页面中的 RouteSettings 对象获取该路由的名称。 (虽然附加到设置对象的参数很好)
换句话说:
Widget build(BuildContext context) {
ModalRoute.of(context).settings.name == null; //bug
ModalRoute.of(context).settings.arguments != null; //ok
...
如果您想知道当前路线的名称,这可能会影响您。 例如,如果你想弹出一些屏幕:
navigator.popUntil(ModalRoute.withName('/login'));
因此,在此问题解决之前,我建议使用routes: 属性。
【讨论】:
routes 是静态的,不提供向小部件传递参数、实现不同的PageRoute 等功能,这就是onGenerateRoute 存在的原因。
在给定的代码中,您会发现如何使用onGenerateRoute 属性,您可以解析参数并将其发送出去,而这对于简单的routes 是不可能的。
FooPage 通过routes 和BarPage 通过onGenerateRoute 导航。
MaterialApp 中的初始设置。
void main() {
runApp(
MaterialApp(
routes: {
'/': (_) => HomePage(), // You can also use MaterialApp's `home` property instead of '/'
'/foo': (_) => FooPage(), // No way to pass an argument to FooPage.
},
onGenerateRoute: (settings) {
if (settings.name == '/bar') {
final value = settings.arguments as int; // Retrieve the value.
return MaterialPageRoute(builder: (_) => BarPage(value)); // Pass it to BarPage.
}
return null; // Let `onUnknownRoute` handle this behavior.
},
),
);
}
home.dart:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('HomePage')),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, '/foo'),
child: Text('Go to FooPage'),
),
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, '/bar', arguments: 42), // Passing argument
child: Text('Go to BarPage'),
),
],
),
),
);
}
}
foo.dart
class FooPage extends StatelessWidget {
@override
Widget build(_) => Scaffold(appBar: AppBar(title: Text('FooPage')));
}
还有bar.dart:
class BarPage extends StatelessWidget {
final int value;
BarPage(this.value);
@override
Widget build(_) => Scaffold(appBar: AppBar(title: Text('BarPage, value = $value')));
}
截图(供参考)
【讨论】:
我的解决方案是重新分配 MaterialPageRoute 的设置,例如:
批处理:
final routes = {
'/': (context) => MainPage(),
};
路由设置:
var onGenerateRoute = (RouteSettings settings) {
final String name = settings.name;
final Function pageContentBuilder = routes[name];
if (pageContentBuilder != null) {
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
settings: settings,
builder: (context) => pageContentBuilder(context, arguments: settings.arguments));
return route;
} else {
final Route route =
MaterialPageRoute(settings: settings,
builder: (context) => pageContentBuilder(context));
return route;
}
}
};
【讨论】:
根据文档(我把链接放在下面),如果路由不包含请求的路由,则使用 onGenerateRoute。
【讨论】:
【讨论】: