Flutter 中的命名路由如何消除重复?

The*_*lis 7 dart flutter flutter-navigation

我不明白为什么有人要使用命名的路线,Navigator.pushNamed()而不是在正常的 方式Navigator.push()

教程页指出:

如果我们需要在应用程序的许多部分导航到同一个屏幕,这可能会导致代码重复。在这些情况下,定义“命名路线”并使用命名路线进行导航会很方便

复制

使用简单路由时将如何生成重复以及如何使用命名路由消除重复?

我不明白有什么区别

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SecondRoute()),
  );
Run Code Online (Sandbox Code Playgroud)

Navigator.pushNamed(context, '/second');
Run Code Online (Sandbox Code Playgroud)

重复情况下

mFe*_*ein 15

考虑您Navigator.push()在许多小部件中使用:

// inside widget A:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute()),
);

// inside widget B:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute()),
);

// inside widget C:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute()),
);
Run Code Online (Sandbox Code Playgroud)

现在假设您需要更改您的应用程序,并且小部件SecondRoute需要在其构造函数上接收一个值。现在您遇到了一个问题,因为您在多个位置拥有相同代码的多个副本,您需要确保更新所有这些副本,这可能很乏味且容易出错:

// inside widget A:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute(
      title: 'Title A',
  )),
);

// inside widget B:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute(
      title: 'Title B',
  )),
)),
);

// inside widget C:
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondRoute(
      title: 'Title A',     // ERROR! Forgot to change the variable after a copy/paste
  )),
)),
);
Run Code Online (Sandbox Code Playgroud)

现在让我们考虑使用命名路由。

首先,我永远不会建议任何人直接将名称直接用于导航,而是使用static变量引用,如果您将来需要更改它,则以更简单和安全的方式进行更改,因为您不能忘记在任何地方更新它,像这样:

class Routes {
  static const String second = '/second';
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是在路由本身内部有一个引用,一个static const Stringinside SecondRoute,所以我们可以将它用作SecondRoute.routeName. 这是 IMO 个人喜好的问题。

然后您的小部件将使用:

// inside widget A:
Navigator.pushNamed(context, Routes.second); // Routes.second is the same as '/second'

// inside widget B:
Navigator.pushNamed(context, Routes.second);

// inside widget C:
Navigator.pushNamed(context, Routes.second);
Run Code Online (Sandbox Code Playgroud)

现在,如果您需要SecondRoute在创建时将参数传递给,您可以使用MaterialApp onGenerateRoute,在集中位置执行此操作,正如本教程更详细地解释的那样。您的代码将更改为:

// inside widget A:
Navigator.pushNamed(context, Routes.second, arguments: 'Title A');

// inside widget B:
Navigator.pushNamed(context, Routes.second, arguments: 'Title B');

// inside widget C:
// You can still make mistakes here, but the chances are smaller.
Navigator.pushNamed(context, Routes.second, arguments: 'Title C');
Run Code Online (Sandbox Code Playgroud)
MaterialApp(
  onGenerateRoute: (settings) {
    if (settings.name == Routes.second) {
      final String title = settings.arguments;

      return MaterialPageRoute(
        builder: (context) => SecondRoute(title: title),
      );
    }
  },
);
Run Code Online (Sandbox Code Playgroud)

重复代码的数量减少了,但另一方面,onGenerateRoute随着您制作更多路线,代码变得更加复杂,因为它们的所有创建都将集中在那里,所以恕我直言,这更多的是个人喜好,而不是一般准则。

  • 因此,基于动态类型(路由名称是“String”,“arguments”是“Object”!)复制粘贴 67 个字符的长片段,可能会导致不同步(您可能会意外地给出用于“B”的路由参数) `A`) 片段比复制粘贴 97 个字符的长片段危险性更小,后者是完全静态类型的(构造函数的调用)并且没有潜在的去同步化(参数通过静态类型与构造函数名称相关联)? (3认同)

jit*_*555 2

我可以看到使用带有命名路由的 Navigate的唯一优点是在 MaterialApp 中声明路由,以便开发人员只能使用指定的路由,即小部件、页面、

如果有人使用除此之外的其他方法,则会给出错误“调用了 onUnknownRoute”。

  • 运行时错误比编译时错误如何更好? (4认同)