Flutter 中 onGenerateRoute 和路由的区别

MSA*_*ish 30 dart flutter

onGenerateRouteFlutter中和路由的好处或用例是什么。

在我的应用程序的第一页里面,MaterialApp我们可以为我们的应用程序定义路由,我们可以用onGenerateRoute.

两者都用于 NamedRoute。

我有一个疑问,在哪种情况下我需要使用路由以及在哪种情况下我需要使用onGenerateRoute

Cop*_*oad 38

routes是静态的,不提供诸如将参数传递给小部件、实现不同的功能PageRoute等功能,这就是onGenerateRoute存在的原因。

在给定的代码中,您会发现如何使用onGenerateRoute属性来解析参数并将其发送出去,这对于 simple 来说是不可能的routes

FooPage被导航一遍routesBarPage一遍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.
      },
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

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'),
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

foo.dart

class FooPage extends StatelessWidget {
  @override
  Widget build(_) => Scaffold(appBar: AppBar(title: Text('FooPage')));
}
Run Code Online (Sandbox Code Playgroud)

bar.dart

class BarPage extends StatelessWidget {
  final int value;
  BarPage(this.value);

  @override
  Widget build(_) => Scaffold(appBar: AppBar(title: Text('BarPage, value = $value')));
}
Run Code Online (Sandbox Code Playgroud)

截图(供参考)

在此输入图像描述


Kir*_*zin 30

注意(见答案下面的评论):

没有错误,只是问题报告者使用不当。这是因为他没有将设置对象传递给 onGenerateRoute 方法返回的新 MaterialPageRoute(请参阅问题的最终评论)。[...]


原始答案提到“错误”:

没有深入研究任何细节,这两个属性做同样的事情,但正如@Alireza 指出的那样routes首先被检查。

此外, usingonGenerateRoute为您提供了一个在推送新路由(页面)之前添加自定义业务逻辑的地方。例如,如果要进行一些初始化。

路线属性:

当使用 Navigator.pushNamed 推送命名路线时,会在此地图中查找路线名称。如果该名称存在,则关联的 WidgetBuilder 用于构建 MaterialPageRoute 以执行到新路由的适当转换,包括英雄动画。

onGenerateRoute 属性:

当应用导航到命名路由时使用的路由生成器回调。... 如果路由不包含请求的路由,则使用此选项。

重要提示: 你真正想知道的是一个已知的bugonGenerateRoute财产。

问题是,如果您使用onGenerateRoute创建命名路由,您将无法从页面中的 RouteSettings 对象获取该路由的名称。(虽然附加到设置对象的参数很好)换句话说:

Widget build(BuildContext context) {
    ModalRoute.of(context).settings.name == null;       //bug
    ModalRoute.of(context).settings.arguments != null;  //ok
    ...
Run Code Online (Sandbox Code Playgroud)

如果您想知道当前路线的名称,这可能会影响您。例如,如果你想弹出一些屏幕:

navigator.popUntil(ModalRoute.withName('/login'));
Run Code Online (Sandbox Code Playgroud)

因此,在解决此问题之前,我建议使用该routes:属性。

  • 您提到的那个错误不是错误,只是问题报告者使用不当。这是因为他没有将设置对象传递给 onGenerateRoute 方法返回的新 MaterialPageRoute (请参阅问题的最终评论)。我刚刚用 flutter 1.12.13 测试了它,它工作得很好。除此之外,与您所说的相反,在该问题中,它的settings.arguments也为空,而不仅仅是settings.name。考虑更改您的答案,而不是提及错误,提醒需要将设置传递给 onGenerateRoute 返回的新 MaterialPageRoute。 (15认同)

Ali*_*iri 6

根据文档(我将链接放在下面),如果路由不包含请求的路由,则使用 onGenerateRoute 。

在GenerateRoute上颤动


小智 6

我的解决方案是重新分配MaterialPageRoute的设置,例如:

批量处理:

final routes = {
  '/': (context) => MainPage(),
};
Run Code Online (Sandbox Code Playgroud)

路由设置:

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;
        }
      }
    };



   
Run Code Online (Sandbox Code Playgroud)