【问题标题】:Difference between onGenerateRoute and routes in FlutterFlutter 中 onGenerateRoute 和路由的区别
【发布时间】:2020-05-06 09:40:31
【问题描述】:

onGenerateRoute 和 Flutter 中的路由有什么好处或用例。

MaterialApp 内第一页的我的应用程序中,我们可以为我们的应用程序定义路由,就像我们可以使用onGenerateRoute 定义的一样。

两者都用于 NamedRoute。

我不确定,什么场景需要使用路由,什么场景需要使用onGenerateRoute

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    注意(见下面的 cmets 答案):

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


    提到“错误”的原始答案:

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

    此外,使用onGenerateRoute 可以让您在推送新路由(页面)之前添加自定义业务逻辑。例如,如果你想做一些初始化。

    routes property:

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

    onGenerateRoute property:

    当应用导航到一个命名的路由生成器回调 路线。 ... 如果路由不包含请求的路由,则使用它。

    重要提示: 您真正想知道的是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: 属性。

    【讨论】:

    • 谢谢你的回答兄弟。我有一个疑问。也就是说,当我们为应用程序编写代码时,我们可以知道哪些页面在我们的应用程序中可用。所以我们可以在路线本身中提及所有内容。那为什么我们需要 onGenerateroute 属性呢?
    • 您提到的那个错误不是错误,只是问题报告者的错误使用。这是因为他没有将设置对象传递给 onGenerateRoute 方法返回的新 MaterialPageRoute(请参阅问题的最终 cmets)。我刚刚用颤振 1.12.13 测试了它,它工作得很好。除此之外,与你所说的相反,在那个问题中它的 settings.arguments 也为空,而不仅仅是 settings.name。考虑更改您的答案而不是提及错误,提醒需要将设置传递给 onGenerateRoute 返回的新 MaterialPageRoute。
    【解决方案2】:

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

    在给定的代码中,您会发现如何使用onGenerateRoute 属性,您可以解析参数并将其发送出去,而这对于简单的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.
          },
        ),
      );
    }
    

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

    截图(供参考)

    【讨论】:

      【解决方案3】:

      我的解决方案是重新分配 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;
              }
            }
          };
      
      
      
         
      

      【讨论】:

        【解决方案4】:

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

        Flutter onGenerateRoute

        【讨论】:

          【解决方案5】:
          • 路由器是静态路由器
          • 在onGenerateRoute的帮助下,我们可以根据条件改变页面。

          【讨论】:

          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
          猜你喜欢
          • 2020-02-15
          • 1970-01-01
          • 2017-02-28
          • 2019-09-28
          • 1970-01-01
          • 1970-01-01
          • 2015-05-28
          • 1970-01-01
          相关资源
          最近更新 更多