Как работают Navigator.push() и Navigator.pop()?
Navigator.push() добавляет новый маршрут на стек экранов, Navigator.pop() — удаляет верхний маршрут и возвращает управление предыдущему экрану; pop() может передавать результат вызывающему экрану.
Навигация во Flutter: Navigator.push() и Navigator.pop()
Flutter использует стек экранов (routes). Navigator.push() добавляет новый маршрут поверх стека, а Navigator.pop() удаляет верхний маршрут и возвращает управление предыдущему экрану.
Navigator.push()
Метод принимает два аргумента: BuildContext и объект Route. Чаще всего используют MaterialPageRoute:
// Переход на новый экран
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DetailScreen(id: 42),
),
);
// Ожидание результата с await
final result = await Navigator.push<String>(
context,
MaterialPageRoute(
builder: (context) => const EditScreen(),
),
);
if (result != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Получено: $result')),
);
}
Navigator.pop()
Закрывает текущий экран. Можно передать результат обратно вызывающему экрану:
// Простое закрытие
Navigator.pop(context);
// Закрытие с передачей результата
Navigator.pop(context, 'Данные сохранены');
Именованные маршруты
Для структурированных приложений удобны именованные маршруты, объявленные в MaterialApp:
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => const HomeScreen(),
'/detail': (context) => const DetailScreen(),
'/settings': (context) => const SettingsScreen(),
},
);
// Переход по имени
Navigator.pushNamed(context, '/detail');
// С аргументами
Navigator.pushNamed(
context,
'/detail',
arguments: {'id': 42, 'title': 'Заголовок'},
);
// Получение аргументов внутри экрана
final args = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
pushReplacement и pushAndRemoveUntil
Для потоков авторизации и онбординга нужны специальные методы:
// Заменяет текущий экран (кнопка "Назад" не вернёт предыдущий)
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const HomeScreen()),
);
// Очищает весь стек и открывает новый экран (например, после логина)
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const DashboardScreen()),
(route) => false, // предикат — false убирает все предыдущие маршруты
);
Go Router как альтернатива
В крупных приложениях рекомендуется пакет go_router, который поддерживает deep links, web URL и декларативные маршруты:
final router = GoRouter(
routes: [
GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
GoRoute(path: '/detail/:id', builder: (context, state) {
final id = state.pathParameters['id']!;
return DetailScreen(id: int.parse(id));
}),
],
);
// Переход
context.go('/detail/42');
context.pop();
Подводные камни
- Вызов
Navigator.pop()на единственном экране в стеке вызывает исключение — проверяйтеNavigator.canPop(context)перед вызовом. - Передача
contextпосле асинхронных операций (await) может привести к ошибке «use_build_context_synchronously» — проверяйтеmountedпосле await. - Именованные маршруты не поддерживают типизированные аргументы на уровне компилятора — ошибки появляются только в рантайме.
- При использовании вложенных
Navigator(например, в BottomNavigationBar) методNavigator.pop()работает только с ближайшим NavigatorState — используйтеNavigator.of(context, rootNavigator: true)для выхода из вложенного стека. - Отсутствие анимации при навигации на Web-платформе — по умолчанию
MaterialPageRouteиспользует платформо-зависимую анимацию, что ломает ожидания пользователей на вебе. pushAndRemoveUntilс предикатом(route) => falseудаляет все маршруты — не оставит возможности вернуться даже через кнопку «Назад» устройства.
Common mistakes
- Сводить «работают
Navigator.push()иNavigator.pop()» к синтаксису и не объяснять render tree. - Игнорировать жизненный цикл, основной поток или момент освобождения ресурсов в сценарии flutter-17.
- Выбирать API по привычке, не проверяя состояние, ошибки, доступность и платформенные ограничения.
What the interviewer is testing
- Формулирует точную модель для «работают
Navigator.push()иNavigator.pop()» и подтверждает ее корректным примером. - Умеет связать ответ с frame scheduling, тестированием и отладкой на устройстве.
- Называет ограничения подхода flutter-17, включая производительность, память и сопровождение.