← Назад к вопросам
Как работает навигация во Flutter? Расскажите о Navigator 2.0?
1.6 Junior🔥 202 комментариев
#Архитектура Flutter#Навигация
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает навигация во Flutter? Navigator 2.0
Навигация во Flutter эволюционировала от простого Navigator 1.0 к современному Navigator 2.0, который предоставляет более гибкую и предсказуемую архитектуру.
Navigator 1.0 (Imperative / Старый подход)
У этого подхода были проблемы:
- Web-навигация (history, deep links) работала плохо
- Сложно управлять стеком маршрутов программно
- Потеря состояния при deep links
// ❌ Старый способ — работает но неудобно
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SecondScreen())
);
Navigator 2.0 (Declarative / Новый подход)
Navigator 2.0 использует declarative routing — состояние приложения определяет стек маршрутов.
Основные компоненты
-
RouteInformationParser — парсит URL в объект состояния:
class MyRouteInformationParser extends RouteInformationParser<AppRouteState> { @override Future<AppRouteState> parseRouteInformation(RouteInformation routeInformation) async { final uri = Uri.parse(routeInformation.location ?? '/'); if (uri.pathSegments.isEmpty) { return AppRouteState.home(); } if (uri.pathSegments[0] == 'details' && uri.pathSegments.length > 1) { final id = uri.pathSegments[1]; return AppRouteState.details(id: id); } return AppRouteState.unknown(); } } -
RouterDelegate — управляет стеком маршрутов на основе состояния:
class MyRouterDelegate extends RouterDelegate<AppRouteState> with ChangeNotifier { final List<Page> _history = []; @override Widget build(BuildContext context) { return Navigator( pages: _history, onPopPage: (route, result) { if (!route.didPop(result)) return false; _history.removeLast(); notifyListeners(); return true; }, ); } @override Future<void> setNewRoutePath(AppRouteState configuration) async { if (configuration is HomeRoute) { _history.clear(); _history.add(MaterialPage(child: HomeScreen())); } else if (configuration is DetailsRoute) { _history.clear(); _history.add(MaterialPage(child: HomeScreen())); _history.add(MaterialPage(child: DetailsScreen(id: configuration.id))); } notifyListeners(); } } -
RouteInformationProvider — уведомляет об изменениях URL:
MaterialApp.router( routeInformationProvider: PlatformRouteInformationProvider( initialRouteInformation: RouteInformation(location: '/'), ), routeInformationParser: MyRouteInformationParser(), routerDelegate: MyRouterDelegate(), )
Современный подход: go_router пакет
В реальной жизни почти никто не пишет Navigator 2.0 вручную — используют go_router:
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(),
routes: [
GoRoute(
path: 'details/:id',
builder: (context, state) => DetailsScreen(
id: state.pathParameters['id']!,
),
),
],
),
],
errorBuilder: (context, state) => ErrorScreen(),
);
MaterialApp.router(
routerConfig: router,
)
Навигация в go_router
// Перейти на экран
context.go('/details/123');
// Вернуться назад
context.pop();
// С параметрами
context.pushNamed('details', pathParameters: {'id': '123'});
// Заменить текущий экран
context.replace('/home');
Преимущества Navigator 2.0
- Web поддержка — URL автоматически обновляются
- Deep links — работают корректно
- История браузера — кнопка "назад" работает правильно
- State restoration — восстановление состояния при переходе
- Predictable — состояние приложения = стек маршрутов
Ключевые отличия
| Аспект | Navigator 1.0 | Navigator 2.0 |
|---|---|---|
| Подход | Imperative | Declarative |
| Web | Плохо | Отлично |
| Deep Links | Сложно | Встроено |
| History | Ручной | Автоматический |
| State | Нужно хранить отдельно | В конфигурации |
На практике
Новые проекты должны использовать go_router — это современный стандарт. Navigator 1.0 остался для обратной совместимости и простых случаев.