Навигация во Flutter: выносим переходы из экранов
Знакомо ли вам чувство, когда экран «знает» слишком много? Он не только рисует интерфейс, но и решает, куда прыгать дальше, создавая новые виджеты и раздавая им зависимости. Это классическая ловушка, которая делает код хрупким и почти невозможным для модульного тестирования.
💡 Паттерн Координатор давно спасает iOS-разработчиков от этой боли, но во Flutter его часто игнорируют. Причина проста: стандартные гайдлайны и популярные пакеты вроде go_router или auto_route поощряют прямые вызовы
context.go() прямо из виджета.Проблема в нарушении принципа единственной ответственности (SRP). Экран не знает контекста приложения: в какой вкладке он находится, какой стек под ним и нужно ли переключать разделы. Эта информация доступна только там, где приложение собирается из экранов.
🔧 Решение основано на принципе «информационного эксперта» из методологии GRASP. Экран должен лишь сообщать о намерении пользователя, а решение о переходе принимает компонент, обладающий полной информацией. Вместо жесткой привязки к маршруту экран использует абстрактный интерфейс или колбэк.
В статье показано, как внедрить этот подход инкрементально. Не нужно менять библиотеку навигации или переписывать всё приложение. Переходы выносятся из экранов по одному, сохраняя работоспособность остальной навигации.
📦 Разобраны три реализации:
✅ Штатный Navigator с
GlobalKey и колбэками.✅ go_router с использованием
StatefulShellRoute для независимых стеков вкладок.✅ auto_route с кодогенерацией и слоем страниц, изолирующим аннотации от экранов.
Ключевая фишка — иерархия роутеров. Каждый уровень знает только о своих непосредственных экранах. Если запрос выходит за пределы текущего стека (например, переход из контактов в ленту), он делегируется вышестоящему уровню —
AppRouter.⚠️ Ограничение? Сложность архитектуры немного растет. Но выигрыш в переиспользуемости и тестируемости окупает это с лихвой. Экран становится «чистым»: его можно тестировать без сконфигурированного роутера, просто передав заглушку.
🔗 Полезные ссылки
Исходный код примера
Документация по навигации в Compose
🔗 Полезные ссылки
💻 example_routing_coordinator_flutter
📚 Navigation with Compose
📰 Читать оригинал на Habr
FlutterPulse — канал о мире Flutter!
#flutter #dart #flutterpulse #flutterpulsehabr