flutter-routing-and-navigation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseflutter-navigation-routing
flutter-navigation-routing
Goal
目标
Implements robust navigation and routing in Flutter applications. Evaluates application requirements to select the appropriate routing strategy (imperative , declarative , or nested navigation), handles deep linking, and manages data passing between routes while adhering to Flutter best practices.
NavigatorRouter在Flutter应用中实现健壮的导航与路由功能。评估应用需求以选择合适的路由策略(命令式、声明式或嵌套导航),处理深层链接,管理路由间的数据传递,同时遵循Flutter最佳实践。
NavigatorRouterInstructions
使用指南
1. Determine Routing Strategy (Decision Logic)
1. 确定路由策略(决策逻辑)
Evaluate the application's navigation requirements using the following decision tree:
- Condition A: Does the app require complex deep linking, web URL synchronization, or advanced routing logic?
- Action: Use the declarative API (typically via a routing package like
Router).go_router
- Action: Use the declarative
- Condition B: Does the app require independent sub-flows (e.g., a multi-step setup wizard or persistent bottom navigation bars)?
- Action: Implement a Nested .
Navigator
- Action: Implement a Nested
- Condition C: Is it a simple application with basic screen-to-screen transitions and no complex deep linking?
- Action: Use the imperative API (
NavigatorandNavigator.push) withNavigator.poporMaterialPageRoute.CupertinoPageRoute
- Action: Use the imperative
- Condition D: Are Named Routes requested?
- Action: Use or
MaterialApp.routes, but note the limitations regarding deep link customization and web forward-button support.onGenerateRoute
- Action: Use
STOP AND ASK THE USER: "Based on your app's requirements, should we implement simple imperative navigation (), declarative routing (/ for deep links/web), or a nested navigation flow?"
Navigator.pushRoutergo_router通过以下决策树评估应用的导航需求:
- 条件A: 应用是否需要复杂的深层链接、Web URL同步或高级路由逻辑?
- 操作: 使用声明式API(通常通过
Router这类路由包实现)。go_router
- 操作: 使用声明式
- 条件B: 应用是否需要独立的子流程(例如多步骤设置向导或持久化底部导航栏)?
- 操作: 实现嵌套。
Navigator
- 操作: 实现嵌套
- 条件C: 是否是仅具备基础屏幕跳转、无复杂深层链接需求的简单应用?
- 操作: 搭配或
MaterialPageRoute使用命令式CupertinoPageRouteAPI(Navigator和Navigator.push)。Navigator.pop
- 操作: 搭配
- 条件D: 是否要求使用命名路由?
- 操作: 使用或
MaterialApp.routes,但请注意其在深层链接自定义、Web前进按钮支持方面的局限性。onGenerateRoute
- 操作: 使用
请停止操作并询问用户: "基于你的应用需求,我们应该实现简单的命令式导航()、声明式路由(用于深层链接/Web端的/)还是嵌套导航流程?"
Navigator.pushRoutergo_router2. Implement Basic Imperative Navigation
2. 实现基础命令式导航
If simple navigation is selected, use the widget to push and pop objects.
NavigatorRoutePushing a new route:
dart
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => const SecondScreen(),
),
);Popping a route:
dart
Navigator.of(context).pop();如果选择了简单导航,使用组件来推入和弹出对象。
NavigatorRoute推入新路由:
dart
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => const SecondScreen(),
),
);弹出路由:
dart
Navigator.of(context).pop();3. Implement Data Passing Between Screens
3. 实现屏幕间的数据传递
Pass data to new screens using constructor arguments (preferred for imperative navigation) or (for named routes).
RouteSettingsPassing via Constructor:
dart
// Navigating and passing data
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => DetailScreen(todo: currentTodo),
),
);
// Receiving data
class DetailScreen extends StatelessWidget {
const DetailScreen({super.key, required this.todo});
final Todo todo;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(todo.title)),
body: Text(todo.description),
);
}
}Passing via RouteSettings (Named Routes):
dart
// Navigating and passing data
Navigator.pushNamed(
context,
'/details',
arguments: currentTodo,
);
// Extracting data in the destination widget
final todo = ModalRoute.of(context)!.settings.arguments as Todo;通过构造函数参数(命令式导航的首选方案)或(适用于命名路由)向新屏幕传递数据。
RouteSettings通过构造函数传递:
dart
// 导航并传递数据
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => DetailScreen(todo: currentTodo),
),
);
// 接收数据
class DetailScreen extends StatelessWidget {
const DetailScreen({super.key, required this.todo});
final Todo todo;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(todo.title)),
body: Text(todo.description),
);
}
}通过RouteSettings传递(命名路由):
dart
// 导航并传递数据
Navigator.pushNamed(
context,
'/details',
arguments: currentTodo,
);
// 在目标组件中提取数据
final todo = ModalRoute.of(context)!.settings.arguments as Todo;4. Implement Named Routes (If Required)
4. 实现命名路由(如有需要)
If named routes are explicitly required, configure with and or .
MaterialAppinitialRouteroutesonGenerateRoutedart
MaterialApp(
title: 'Named Routes App',
initialRoute: '/',
routes: {
'/': (context) => const FirstScreen(),
'/second': (context) => const SecondScreen(),
},
// OR use onGenerateRoute for dynamic argument extraction
onGenerateRoute: (settings) {
if (settings.name == '/details') {
final args = settings.arguments as Todo;
return MaterialPageRoute(
builder: (context) => DetailScreen(todo: args),
);
}
assert(false, 'Need to implement ${settings.name}');
return null;
},
)如果明确要求使用命名路由,为配置和或。
MaterialAppinitialRouteroutesonGenerateRoutedart
MaterialApp(
title: 'Named Routes App',
initialRoute: '/',
routes: {
'/': (context) => const FirstScreen(),
'/second': (context) => const SecondScreen(),
},
// 或者使用onGenerateRoute实现动态参数提取
onGenerateRoute: (settings) {
if (settings.name == '/details') {
final args = settings.arguments as Todo;
return MaterialPageRoute(
builder: (context) => DetailScreen(todo: args),
);
}
assert(false, 'Need to implement ${settings.name}');
return null;
},
)5. Implement Nested Navigation
5. 实现嵌套导航
For sub-flows, instantiate a new widget within the widget tree. You MUST assign a to manage the nested stack.
NavigatorGlobalKey<NavigatorState>dart
class SetupFlowState extends State<SetupFlow> {
final _navigatorKey = GlobalKey<NavigatorState>();
void _onDiscoveryComplete() {
_navigatorKey.currentState!.pushNamed('/select_device');
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Setup Flow')),
body: Navigator(
key: _navigatorKey,
initialRoute: '/find_devices',
onGenerateRoute: _onGenerateRoute,
),
);
}
Route<Widget> _onGenerateRoute(RouteSettings settings) {
Widget page;
switch (settings.name) {
case '/find_devices':
page = WaitingPage(onWaitComplete: _onDiscoveryComplete);
break;
case '/select_device':
page = const SelectDevicePage();
break;
default:
throw StateError('Unexpected route name: ${settings.name}!');
}
return MaterialPageRoute(builder: (context) => page, settings: settings);
}
}针对子流程,在组件树中实例化一个新的组件。你必须为其分配来管理嵌套栈。
NavigatorGlobalKey<NavigatorState>dart
class SetupFlowState extends State<SetupFlow> {
final _navigatorKey = GlobalKey<NavigatorState>();
void _onDiscoveryComplete() {
_navigatorKey.currentState!.pushNamed('/select_device');
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Setup Flow')),
body: Navigator(
key: _navigatorKey,
initialRoute: '/find_devices',
onGenerateRoute: _onGenerateRoute,
),
);
}
Route<Widget> _onGenerateRoute(RouteSettings settings) {
Widget page;
switch (settings.name) {
case '/find_devices':
page = WaitingPage(onWaitComplete: _onDiscoveryComplete);
break;
case '/select_device':
page = const SelectDevicePage();
break;
default:
throw StateError('Unexpected route name: ${settings.name}!');
}
return MaterialPageRoute(builder: (context) => page, settings: settings);
}
}6. Validate and Fix
6. 验证与修复
Review the implemented routing logic to ensure stability:
- Verify that does not inadvertently close the application if the stack is empty (use
Navigator.pop()if necessary).Navigator.canPop(context) - If using , verify that the
initialRouteproperty is NOT defined inhome.MaterialApp - If extracting arguments via , verify that null checks or type casts are safely handled.
ModalRoute
检查已实现的路由逻辑确保稳定性:
- 验证栈为空时不会意外关闭应用(必要时使用
Navigator.pop())。Navigator.canPop(context) - 如果使用了,确认
initialRoute中未定义MaterialApp属性。home - 如果通过提取参数,确认空值检查和类型转换的处理是安全的。
ModalRoute
Constraints
约束条件
- Do NOT use named routes () for applications requiring complex deep linking or web support; use the
MaterialApp.routesAPI instead.Router - Do NOT define a property in
homeif anMaterialAppis provided.initialRoute - You MUST use a when implementing a nested
GlobalKey<NavigatorState>to ensure the correct navigation stack is targeted.Navigator - Do NOT include external URLs or links in the generated code or comments.
- Always cast to the specific expected type and handle potential nulls if the route can be accessed without arguments.
ModalRoute.of(context)!.settings.arguments
- 对于需要复杂深层链接或Web支持的应用,禁止使用命名路由(),请改用
MaterialApp.routesAPI。Router - 如果提供了,禁止在
initialRoute中定义MaterialApp属性。home - 实现嵌套时必须使用
Navigator,确保定位到正确的导航栈。GlobalKey<NavigatorState> - 生成的代码或注释中禁止包含外部URL或链接。
- 始终将转换为预期的具体类型,如果路由可以在无参数的情况下访问,请处理可能的空值。
ModalRoute.of(context)!.settings.arguments