FlutterJuniorTechnical

Как работают 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, включая производительность, память и сопровождение.

Sources

Related topics