Миграция мобильного приложения на новую версию Flutter SDK
Flutter меняет публичный API чаще, чем кажется. Переход с Flutter 2.x на 3.x принёс null safety как обязательное требование, отказ от WidgetsFlutterBinding.ensureInitialized() в ряде случаев, новый Navigator 2.0 и изменения в MaterialState → WidgetState. Миграция производственного приложения — это не просто flutter pub upgrade.
Что реально ломается при мажорном апгрейде
Null safety: за пределами dart migrate
Инструмент dart migrate делает 70-80% работы — проставляет ? и ! там, где анализатор может вывести nullability. Остальные 20-30% — ручная работа, и именно там скрыты баги.
Типичный случай: плагин из pub.dev не перешёл на null safety и заморожен. Варианты: fork с патчем, замена на альтернативный пакет, написание обёртки. В проекте с 40+ зависимостями это превращается в неделю работы только на зависимости.
Ещё опаснее — код, который проходит миграцию без ошибок, но меняет поведение. late переменная без инициализации бросает LateInitializationError в рантайме там, где раньше был просто null. Ловится только тестами или в продакшене.
Breaking changes в Material 3
Flutter 3.16+ переключил useMaterial3: true по умолчанию. Если в приложении кастомная тема через ThemeData, часть компонентов начинает выглядеть иначе: изменились размеры кнопок, отступы в AppBar, шрифтовая иерархия TextTheme. Приложения, отклонённые из-за внешних изменений после апгрейда — не редкость.
Решение: явно задать useMaterial3: false на время миграции, затем поэтапно переходить на M3 по компоненту.
Изменения в Navigator и роутинге
Если приложение использует go_router, каждый мажорный релиз пакета ломает API по-новому. Переход с go_router 6.x на 10.x — это полный рерайт конфигурации роутов: GoRoute + ShellRoute вместо вложенных GoRoute, изменения в redirect callback сигнатуре, новый StatefulShellRoute для persistent navigation.
Изменения в рендеринге: Impeller
Flutter 3.10+ включил Impeller по умолчанию на iOS (Android — опционально). Impeller убирает jank от компиляции шейдеров, но ломает кастомные CustomPainter реализации, использующие нестандартные BlendMode или ImageFilter. После включения Impeller нужно прогнать все анимации и кастомные виджеты на реальных устройствах.
Процесс миграции
Аудит зависимостей — первый шаг. flutter pub outdated показывает что устарело, но не показывает breaking changes. Смотрим CHANGELOG каждого пакета из pubspec.yaml вручную для мажорных версий. Зависимости делим на три категории:
- обновляются без изменений кода
- требуют изменений кода (API changes)
- нет совместимой версии — нужна замена или fork
Feature-flag подход для крупных приложений. Создаём migration ветку, обновляем SDK и пакеты, фиксируем все ошибки компиляции. Затем исправляем поэтапно, начиная с core-слоя (модели, репозитории) и заканчивая UI.
Тестирование после миграции:
-
flutter analyze— статический анализ без предупреждений -
flutter test— весь существующий suite должен проходить - Golden tests для UI-компонентов (если используются) нужно перегенерировать — Impeller рендерит пиксели иначе
- Smoke-тест на физических устройствах: iOS + Android, бюджетный Android обязателен
Конкретные проблемы из практики
В проекте (e-commerce, Flutter 2.8 → 3.19) основная трудность была не в коде, а в плагине flutter_local_notifications. Между версиями 9.x и 16.x изменился весь Android-сайд: новый FlutterLocalNotificationsPlugin.initialize() с InitializationSettings, обязательный onDidReceiveNotificationResponse вместо deprecated колбека. Плюс Android 13 требует явного POST_NOTIFICATIONS permission — без него тихо не работает.
Другой случай — image_picker после обновления начал возвращать XFile вместо File. Везде в коде File(imagePicker.path) заменяли на File(xFile.path) — механически, но их было 23 использования в разных экранах.
Сроки
| Масштаб приложения | Типичный срок миграции |
|---|---|
| Small (< 20 экранов, < 15 зависимостей) | 3-5 дней |
| Medium (20-60 экранов, 15-40 зависимостей) | 1-3 недели |
| Large (60+ экранов, сложная архитектура) | 3-6 недель |
Стоимость рассчитывается индивидуально после аудита репозитория и списка зависимостей.







