Ответ
При реализации навигации в Flutter я работаю со следующими ключевыми классами и концепциями:
1. Navigator — центральный класс, управляющий стеком маршрутов (Route):
// Простой переход
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsScreen(product: product)),
);
// Возврат с результатом
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
// Возврат назад
Navigator.pop(context, {'selected': true});
2. Route и его реализации:
- MaterialPageRoute — стандартный маршрут для Material Design
- CupertinoPageRoute — для iOS-стиля
- PageRouteBuilder — для кастомных анимаций переходов:
PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => DetailsScreen(), transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, )
3. RouteSettings — хранение конфигурации маршрута:
Navigator.pushNamed(
context,
'/user/profile',
arguments: UserProfileArgs(userId: 123),
);
// В целевом виджете
final args = ModalRoute.of(context)!.settings.arguments as UserProfileArgs;
4. ModalRoute — для получения информации о текущем маршруте:
final currentRoute = ModalRoute.of(context);
final isCurrent = currentRoute?.isCurrent ?? false;
5. Для именованной навигации (классический подход):
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailsScreen(),
'/settings': (context) => SettingsScreen(),
},
onGenerateRoute: (settings) {
if (settings.name == '/user/:id') {
final id = settings.name!.split('/').last;
return MaterialPageRoute(
builder: (context) => UserScreen(userId: id),
);
}
return null;
},
);
В современных проектах я часто использую пакеты для более декларативной и типобезопасной навигации:
- go_router — популярный выбор с глубокими ссылками и guard-логикой
- auto_route — генерация маршрутов по аннотациям, полная типобезопасность
- beamer — основан на Router API, поддерживает вложенные маршруты
Ответ 18+ 🔞
Э, слушай, вот сидишь ты такой, пишешь на Flutter, и тут бац — навигация. Ну, на первый взгляд, вроде всё просто: туда перешли, обратно вернулись. Но как начинаешь копать, понимаешь, что там под капотом — ёперный театр, целая вселенная. Давай разберём по косточкам, чтобы не было потом «я нихуя не понял».
1. Navigator — это главный пахан Этот класс — типа диспетчера, который командует целой очередью экранов (стеком маршрутов, если по-умному). Он решает, какой экран сверху, какой скрыт, а какой вообще нахуй послать.
// Самый простой способ ткнуть пользователя на новый экран
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsScreen(product: product)),
);
// А вот это уже интереснее: уходим, но ждём ответа, как письма из армии
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
// Всё надоело? Возвращаемся обратно, как будто ничего и не было
Navigator.pop(context, {'selected': true});
Без него — никуда. Абсолютный царь и бог.
2. Route — а это уже солдаты, разные и всякие Маршрут — это по сути инструкция, как показать новый экран. Есть стандартные ребята:
- MaterialPageRoute — для андроидоподобных приложений, с привычной анимацией снизу-вверх.
- CupertinoPageRoute — для тех, кто любит яблочный стиль, с анимацией справа-налево.
- PageRouteBuilder — а это для тех, кому стандартные анимации — как серая масса, и хочется своей уникальной хуйни. Тут можно выкручиваться на полную.
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => DetailsScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// Вот тут уже твори, что хочешь. Например, плавное появление
return FadeTransition(opacity: animation, child: child);
},
)
Чувствуешь мощь? Можно сделать так, чтобы экран выезжал на хуй с горы или появлялся, как манда с ушами. Полная свобода, но и ответственность, конечно.
3. RouteSettings — паспорт маршрута
Ну, а как передать данные на новый экран, кроме как в конструктор? Вот для этого и есть arguments. Кидаешь что угодно, ловишь на той стороне.
// Кидаем пользователя на профиль и передаём ID
Navigator.pushNamed(
context,
'/user/profile',
arguments: UserProfileArgs(userId: 123), // Любой объект!
);
// А на экране профиля вытаскиваем это добро, как из кармана
final args = ModalRoute.of(context)!.settings.arguments as UserProfileArgs;
Главное — не забыть привести к правильному типу, а то будет null, и волнение ебать.
4. ModalRoute — шпион в стане врага Иногда надо узнать про текущий маршрут: а он активен? а как его зовут? Вот тут и пригодится.
final currentRoute = ModalRoute.of(context);
final isCurrent = currentRoute?.isCurrent ?? false; // true, если экран сейчас виден
Полезная хуйня, когда логика зависит от того, видит ли пользователь этот экран или уже ушёл пить чай.
5. Именованная навигация — чтобы не путаться в пути
Когда экранов становится овердохуища, push с MaterialPageRoute превращаются в ад. Тут на помощь приходят именованные маршруты. Прописываешь все пути в одном месте, как карту метро.
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailsScreen(),
'/settings': (context) => SettingsScreen(),
},
onGenerateRoute: (settings) { // А это — для динамических путей, типа /user/123
if (settings.name == '/user/:id') {
final id = settings.name!.split('/').last;
return MaterialPageRoute(
builder: (context) => UserScreen(userId: id),
);
}
return null; // Не нашли? Ну и хуй с ним.
},
);
Старый, добрый, проверенный способ. Но, чувак, в серьёзных проектах он иногда начинает трещать по швам. Типобезопасность там, глубокие ссылки, логика доступа...
Поэтому в современных проектах все умные дяди берут пакеты:
- go_router — сейчас, бля, самый модный. Управление через декларативную конфигурацию, охрана маршрутов (guards), глубокие ссылки из коробки. Мощная штука.
- auto_route — для параноиков, которые хотят полную типобезопасность. Ты описываешь маршруты аннотациями, а пакет генерирует код. Ошибка в названии маршрута? Компилятор тебя нахуй пошлёт сразу, а не в рантайме.
- beamer — построен на основе низкоуровневого Router API, хорошо заточен под сложные, вложенные навигационные структуры.
Короче, выбор есть. Можно и голым Navigator-ом орудовать, если проект маленький. А можно взять go_router и чувствовать себя повелителем навигации. Главное — понять базовые принципы, а там уже, как говорится, да похуй, какой инструмент использовать, лишь бы работало и не разваливалось при первом же чихе.