Flutter中路由配置的各种方案

我来为你详细介绍Flutter中路由配置的各种方案,包括它们的特色、优缺点和实际代码示例。

1. 基础路由(MaterialApp.routes)

特色

  • Flutter最基础的路由配置方式
  • 适合简单的应用场景
  • 配置简单直观

优缺点

优点 :简单易用,学习成本低 缺点:功能有限,不支持复杂路由场景

实际代码

dart 复制代码
// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '基础路由示例',
      initialRoute: '/',
      routes: {
        '/': (context) => HomePage(),
        '/details': (context) => DetailsPage(),
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 导航到详情页
            Navigator.pushNamed(context, '/details');
          },
          child: Text('前往详情页'),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('详情页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

传参方式

基础路由不支持直接传参,需要通过ModalRoute获取参数:

dart 复制代码
// 传参
Navigator.pushNamed(context, '/details', arguments: {
  'id': 123,
  'title': '示例标题'
});

// 获取参数
class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
    final id = args['id'];
    final title = args['title'];
    
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Text('ID: $id'),
      ),
    );
  }
}

2. onGenerateRoute(动态路由)

特色

  • 支持动态路由生成
  • 可以处理复杂的路由逻辑
  • 支持参数验证和转换

优缺点

优点 :灵活性强,支持复杂路由逻辑 缺点:配置相对复杂

实际代码

dart 复制代码
// main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '动态路由示例',
      initialRoute: '/',
      onGenerateRoute: (RouteSettings settings) {
        switch (settings.name) {
          case '/':
            return MaterialPageRoute(builder: (context) => HomePage());
          case '/details':
            final args = settings.arguments as Map<String, dynamic>?;
            return MaterialPageRoute(
              builder: (context) => DetailsPage(
                id: args?['id'] ?? 0,
                title: args?['title'] ?? '默认标题',
              ),
            );
          case '/profile':
            final userId = settings.arguments as String?;
            return MaterialPageRoute(
              builder: (context) => ProfilePage(userId: userId ?? 'unknown'),
            );
          default:
            return MaterialPageRoute(
              builder: (context) => NotFoundPage(routeName: settings.name ?? ''),
            );
        }
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/details', arguments: {
                  'id': 123,
                  'title': '动态路由示例'
                });
              },
              child: Text('前往详情页'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, '/profile', arguments: 'user123');
              },
              child: Text('前往个人主页'),
            ),
          ],
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  final int id;
  final String title;

  const DetailsPage({required this.id, required this.title});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          children: [
            Text('ID: $id'),
            Text('标题: $title'),
          ],
        ),
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  final String userId;

  const ProfilePage({required this.userId});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('个人主页')),
      body: Center(
        child: Text('用户ID: $userId'),
      ),
    );
  }
}

class NotFoundPage extends StatelessWidget {
  final String routeName;

  const NotFoundPage({required this.routeName});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('页面未找到')),
      body: Center(
        child: Text('路由 "$routeName" 不存在'),
      ),
    );
  }
}

3. 命名路由(Named Routes)

特色

  • 使用字符串标识路由
  • 支持路由堆栈管理
  • 适合中大型应用

优缺点

优点 :路由管理清晰,支持pushNamed、popUntil等操作 缺点:参数传递需要额外处理

实际代码

dart 复制代码
// routes.dart
class AppRoutes {
  static const String home = '/';
  static const String details = '/details';
  static const String profile = '/profile';
  static const String settings = '/settings';
}

// main.dart
import 'package:flutter/material.dart';
import 'routes.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '命名路由示例',
      initialRoute: AppRoutes.home,
      routes: {
        AppRoutes.home: (context) => HomePage(),
        AppRoutes.details: (context) => DetailsPage(),
        AppRoutes.profile: (context) => ProfilePage(),
        AppRoutes.settings: (context) => SettingsPage(),
      },
      onGenerateRoute: (settings) {
        // 处理未定义的路由
        if (settings.name == '/unknown') {
          return MaterialPageRoute(
            builder: (context) => NotFoundPage(),
          );
        }
        return null;
      },
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () {
                // 普通跳转
                Navigator.pushNamed(context, AppRoutes.details);
              },
              child: Text('前往详情页'),
            ),
            ElevatedButton(
              onPressed: () {
                // 替换当前路由
                Navigator.pushReplacementNamed(context, AppRoutes.profile);
              },
              child: Text('替换到个人主页'),
            ),
            ElevatedButton(
              onPressed: () {
                // 跳转并清除所有路由
                Navigator.pushNamedAndRemoveUntil(
                  context,
                  AppRoutes.settings,
                  (route) => false,
                );
              },
              child: Text('跳转到设置页(清除堆栈)'),
            ),
          ],
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('详情页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('个人主页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('设置页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class NotFoundPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('页面未找到')),
      body: Center(
        child: Text('页面不存在'),
      ),
    );
  }
}

4. 第三方路由库(go_router)

特色

  • 声明式路由管理
  • 支持深度链接
  • 强大的路由守卫

优缺点

优点 :功能强大,支持复杂路由场景 缺点:需要学习第三方库

实际代码

首先添加依赖:

yaml 复制代码
# pubspec.yaml
dependencies:
  go_router: ^14.0.0
dart 复制代码
// main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final GoRouter _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => HomePage(),
        routes: [
          GoRoute(
            path: 'details/:id',
            builder: (context, state) {
              final id = state.pathParameters['id']!;
              final title = state.uri.queryParameters['title'] ?? '默认标题';
              return DetailsPage(id: int.parse(id), title: title);
            },
          ),
          GoRoute(
            path: 'profile',
            builder: (context, state) => ProfilePage(),
          ),
        ],
      ),
    ],
    errorBuilder: (context, state) => NotFoundPage(),
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'GoRouter示例',
      routerConfig: _router,
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () {
                // 路径参数 + 查询参数
                context.go('/details/123?title=GoRouter示例');
              },
              child: Text('前往详情页'),
            ),
            ElevatedButton(
              onPressed: () {
                // 相对路径
                context.go('/profile');
              },
              child: Text('前往个人主页'),
            ),
            ElevatedButton(
              onPressed: () {
                // 传递额外参数
                context.go('/details/456', extra: {'from': 'home'});
              },
              child: Text('带额外参数跳转'),
            ),
          ],
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  final int id;
  final String title;

  const DetailsPage({required this.id, required this.title});

  @override
  Widget build(BuildContext context) {
    final extra = GoRouterState.of(context).extra as Map<String, dynamic>?;
    
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Center(
        child: Column(
          children: [
            Text('ID: $id'),
            Text('标题: $title'),
            if (extra != null) Text('来源: ${extra['from']}'),
            ElevatedButton(
              onPressed: () {
                context.pop();
              },
              child: Text('返回'),
            ),
          ],
        ),
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('个人主页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            context.pop();
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class NotFoundPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('页面未找到')),
      body: Center(
        child: Text('页面不存在'),
      ),
    );
  }
}

5. 自定义路由管理器

特色

  • 完全自定义控制
  • 适合特殊需求
  • 高度灵活

优缺点

优点 :完全控制路由逻辑 缺点:开发成本高

实际代码

dart 复制代码
// custom_router.dart
import 'package:flutter/material.dart';

class CustomRouteManager {
  static final CustomRouteManager _instance = CustomRouteManager._internal();
  factory CustomRouteManager() => _instance;
  CustomRouteManager._internal();

  final Map<String, WidgetBuilder> _routes = {};
  final Map<String, Route<dynamic> Function(RouteSettings)> _routeFactories = {};

  void registerRoute(String path, WidgetBuilder builder) {
    _routes[path] = builder;
  }

  void registerRouteFactory(String path, 
      Route<dynamic> Function(RouteSettings) factory) {
    _routeFactories[path] = factory;
  }

  Route<dynamic>? generateRoute(RouteSettings settings) {
    // 优先使用路由工厂
    if (_routeFactories.containsKey(settings.name)) {
      return _routeFactories[settings.name]!(settings);
    }
    
    // 使用普通路由
    if (_routes.containsKey(settings.name)) {
      return MaterialPageRoute(
        builder: _routes[settings.name]!,
        settings: settings,
      );
    }
    
    return null;
  }

  void navigateTo(BuildContext context, String path, 
      {Map<String, dynamic>? arguments}) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => _buildPage(path, arguments),
      ),
    );
  }

  Widget _buildPage(String path, Map<String, dynamic>? arguments) {
    if (_routes.containsKey(path)) {
      return _routes[path]!(BuildContext(null));
    }
    return NotFoundPage(routeName: path);
  }
}

// main.dart
import 'package:flutter/material.dart';
import 'custom_router.dart';

void main() {
  // 注册路由
  final router = CustomRouteManager();
  router.registerRoute('/', (context) => HomePage());
  router.registerRoute('/details', (context) => DetailsPage());
  
  runApp(MyApp(router: router));
}

class MyApp extends StatelessWidget {
  final CustomRouteManager router;

  const MyApp({required this.router});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '自定义路由示例',
      home: HomePage(),
      onGenerateRoute: router.generateRoute,
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('首页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            CustomRouteManager().navigateTo(context, '/details', 
              arguments: {'id': 123, 'title': '自定义路由'});
          },
          child: Text('前往详情页'),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('详情页')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('返回'),
        ),
      ),
    );
  }
}

class NotFoundPage extends StatelessWidget {
  final String routeName;

  const NotFoundPage({required this.routeName});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('页面未找到')),
      body: Center(
        child: Text('路由 "$routeName" 不存在'),
      ),
    );
  }
}

总结对比

方案 适用场景 优点 缺点
基础路由 简单应用 简单易用 功能有限
动态路由 中等复杂度 灵活性强 配置复杂
命名路由 中大型应用 管理清晰 参数处理麻烦
go_router 复杂应用 功能强大 学习成本高
自定义路由 特殊需求 完全控制 开发成本高

参数传递方式总结

  1. 路径参数/user/123state.pathParameters['id']
  2. 查询参数/user?id=123state.uri.queryParameters['id']
  3. 额外参数arguments属性 → ModalRoute.of(context)!.settings.arguments
  4. 构造函数传参:最推荐的方式,类型安全

选择哪种方案取决于你的应用复杂度、团队熟悉度和具体需求。对于大多数应用,推荐使用onGenerateRoutego_router

相关推荐
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端
爱敲代码的小鱼12 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax