Ответ
Navigator 1.0 (императивный) — это классический стековый навигатор, управляемый прямыми командами push и pop. Он прост для понимания, но сложен для синхронизации с состоянием приложения (например, с глубокими ссылками).
// Императивный подход
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const DetailsScreen()),
);
Navigator 2.0 (декларативный) — это более новая парадигма, где стек страниц (pages) является частью состояния вашего приложения. Вы управляете навигацией, изменяя список страниц, а Flutter сам анимирует переходы.
class AppRouter extends StatefulWidget {
const AppRouter({super.key});
@override
State<AppRouter> createState() => _AppRouterState();
}
class _AppRouterState extends State<AppRouter> {
// Состояние навигации — список страниц
List<Page<dynamic>> _pages = [const MaterialPage(child: HomeScreen())];
void _openDetails() {
setState(() {
_pages = [..._pages, const MaterialPage(child: DetailsScreen())];
});
}
@override
Widget build(BuildContext context) {
return Navigator(
pages: _pages,
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
// Обновляем состояние при попытке возврата
setState(() => _pages.removeLast());
return true;
},
);
}
}
Ключевые преимущества Navigator 2.0:
- Полный контроль: Стек страниц — часть вашего состояния, что упрощает интеграцию с state-менеджерами (Bloc, Riverpod).
- Глубокие ссылки: Прямая синхронизация URL (в веб) или роута с состоянием навигации.
- Сложные сценарии: Упрощает реализацию вложенных навигаторов, модальных потоков.
На практике для большинства приложений я использую пакеты-надстройки, которые реализуют Navigator 2.0, такие как go_router или auto_route. Они скрывают boilerplate-код, предоставляя удобный API для объявления роутов и работы с глубокими ссылками.