AI-кодинг для Flutter и мобильной разработки: что упускают все гайды

Что такое AI-кодинг для Flutter?

AI-кодинг для Flutter — использование LLM-ассистентов для генерации Dart-кода, моделей данных и Edge Functions в Flutter-проекте с ключевым ограничением: AI не должен редактировать сгенерированные файлы (.freezed.dart, .g.dart, .config.dart), которые build_runner перезапишет при следующей сборке. Основные сценарии сбоев — устаревший BuildContext в коллбэках, паттерны Riverpod до версии 3.0 и баги layout, проявляющиеся только на реальных устройствах.

TL;DR

  • -AI спотыкается на Flutter из-за глубоких widget trees, устаревшего BuildContext в коллбэках и цепочек кодогенерации (build_runner, freezed, riverpod_generator)
  • -Никогда не давать AI редактировать .freezed.dart, .g.dart, .config.dart — build_runner перезапишет при следующей сборке
  • -Riverpod 3.0 (сентябрь 2025) принёс offline persistence и mutations; модели, обученные до этого, генерируют устаревшие паттерны
  • -AI лучше всего работает с freezed data classes (точность 95%+) и Supabase Edge Functions; хуже всего — с layout и navigation context
  • -Решение: жёсткие правила в CLAUDE.md, MCP-инструменты для актуальной документации Dart, контекст на уровне виджета вместо экрана

Большинство примеров AI-кодинга - про React и Express. «Cursor написал TODO-приложение за 10 минут!» Звучит впечатляюще, пока не пробуешь то же самое на Flutter с Riverpod, 122 зависимостями и цепочкой кодогенерации из freezed + build_runner + injectable. Тут начинаются нюансы.

У меня Flutter-проект на продакшне - JourneyBay, travel-приложение. 18 feature-модулей, 73 edge functions на Supabase, 64 миграции базы, Clean Architecture. Полгода ежедневной работы с Claude Code, до этого - с Cursor. Расскажу, что я выяснил про AI на Flutter-стеке и что обычно остаётся за кадром в гайдах.

Почему AI спотыкается на мобильной разработке

Дело не в качестве моделей. Дело в специфике Flutter, которую веб-ориентированные обзоры обычно не затрагивают.

Widget trees - сложная задача для контекста

Flutter-виджет - это дерево. Вложенное. Глубоко. Типичный экран - 8-12 уровней вложенности: ScaffoldSafeAreaColumnExpandedListView.builderCardPaddingRowFlexibleText. И каждый уровень влияет на поведение дочерних.

AI-модели видят этот код как последовательность токенов. Они не «понимают», что Flexible внутри Row ведёт себя иначе, чем Flexible внутри Column. Что const перед EdgeInsets ломается, если цвет берётся из runtime-темы. Что overflow: TextOverflow.ellipsis без maxLines не работает.

Результат: AI генерирует виджеты, которые выглядят правильно в сниппете, но ломаются на реальных устройствах. Overflow на узком экране. Неправильная раскладка в landscape. Жёлтые полосы на debug-сборке.

BuildContext - невидимая ловушка

BuildContext в Flutter - штука контринтуитивная. Контекст внутри build() и контекст виджетов, которые build() возвращает - это разные объекты. AI-инструменты генерируют навигационный код с GoRouter, который компилируется, но ведёт на неправильный маршрут, потому что использует не тот контекст.

Я ловил это трижды за первый месяц. Claude Code уверенно пишет context.go('/settings') внутри callback, где context уже не тот. Cursor - то же самое. Оба инструмента не знают про Builder widget, который решает проблему.

Кодогенерация: build_runner, freezed, riverpod_generator

Про это почти не пишут. Flutter-проект на Clean Architecture использует кодогенерацию:

@freezed → build_runner → *.freezed.dart
@riverpod → build_runner → *.g.dart
@injectable → build_runner → *.config.dart
@JsonSerializable → build_runner → *.g.dart

AI не знает, что после изменения модели нужно запустить dart run build_runner build --delete-conflicting-outputs. Он редактирует .freezed.dart напрямую - а при следующем build файл перезаписывается. Я терял изменения дважды, пока не добавил в CLAUDE.md жёсткое правило: «Никогда не редактируй файлы с .freezed.dart, .g.dart, .config.dart».

То же с локализацией. ARB-файлы - source of truth. AI правит сгенерированные app_localizations.dart вместо ARB. Следующий flutter pub get затирает все правки.

Riverpod 3.0 - знания AI устарели

Riverpod 3.0 вышел в сентябре 2025 с offline persistence, mutations, Ref.mounted, автоматическим retry. Все AI-модели, обученные до этой даты, генерируют код с устаревшими паттернами. Copilot до сих пор не знает про аргумент spacing в Row и Column, добавленный в Flutter 3.27.

Проблема системная. Мобильные фреймворки обновляются быстрее, чем AI-модели переобучаются.

Что реально работает на Flutter

Теперь о хорошем. Есть вещи, которые AI делает на Flutter отлично - если знать, как к этому подойти.

freezed-модели и data-классы

Это sweet spot для AI. Модель данных - шаблонная работа: поля, fromJson, toJson, copyWith. Claude Code генерирует freezed-модели с 95%+ точностью. Я описываю структуру - он пишет @freezed class, добавляет сериализацию, создаёт factory constructors.

// Промпт: "Создай модель TripDay с полями date, title, list of activities, optional notes"
// Claude Code выдаёт:
@freezed
class TripDay with _$TripDay {
  const factory TripDay({
    required DateTime date,
    required String title,
    required List<Activity> activities,
    String? notes,
  }) = _TripDay;

  factory TripDay.fromJson(Map<String, dynamic> json) =>
      _$TripDayFromJson(json);
}

Работает с первой попытки. Но после генерации нужен build_runner - и AI должен это знать.

Бизнес-логика и use cases

Domain-слой в Clean Architecture - второе место, где AI силён. Use cases обычно невелики: принять параметры → вызвать репозиторий → обработать ошибку → вернуть Either<Failure, T>. Claude Code копирует паттерн из соседних use cases и адаптирует.

Принятие кода на domain-задачах у меня: ~87%. Выше, чем на любом другом слое.

Supabase edge functions из Flutter-контекста

Через MCP Claude Code видит и Flutter-код, и Supabase-схему одновременно. Я говорю: «Создай edge function для обновления trip-данных, тип запроса - вот эта Dart-модель». Claude Code:

  1. Читает Dart-модель через файл
  2. Генерирует TypeScript-типы, совместимые с ней
  3. Пишет edge function с обработкой ошибок по нашему shared-паттерну
  4. Добавляет валидацию входных данных

Это сквозная задача, для которой нужен доступ к обоим контекстам одновременно - и MCP это даёт.

Тесты domain-слоя

Claude Code пишет unit-тесты для use cases и репозиториев лучше, чем для UI. Причина простая: domain-тесты линейные. Вход → выход. Mock репозитория → проверка результата. Нет виджет-дерева, нет BuildContext, нет async-UI.

Наши 61 cross-provider тест для AuthBridge - пример того, как Claude Code генерирует тесты, проходящие через реальный production code path. Но это потребовало детальных правил в CLAUDE.md: «Все тесты используют реальный AuthBridge, не симуляцию. Mock только внешние зависимости».

Где AI проваливается на Flutter

UI-вёрстка: красиво, но хрупко

AI генерирует виджеты, которые выглядят правильно на одном устройстве. На реальном парке устройств - проблемы:

  • Overflow на экранах меньше 375px
  • Text без maxLines + overflow: TextOverflow.ellipsis
  • Row с длинным текстом без Flexible/Expanded
  • Image без errorBuilder - крэш при 404
  • Touch targets меньше 44x44 dp

Я добавил в CLAUDE.md секцию UX Rules, которая проверяется автоматически. Это помогло, но не решило проблему полностью. AI не тестирует на разных размерах экрана - проверка остаётся на разработчике.

Архитектура при масштабировании

AI-код, работающий на 100 пользователях, разваливается на 50,000. AI по умолчанию тяготеет к setState или единственному ChangeNotifier. На 20+ фичах это вызывает каскадные rebuilds: изменение одного поля перерисовывает пол-экрана.

Claude Code с Riverpod справляется лучше - но только если в CLAUDE.md прописаны правила: «Используй Riverpod providers для state, не StatefulWidget. Создавай providers с @riverpod аннотацией».

Без этих правил AI выбирает путь наименьшего сопротивления.

Платформо-специфичный код

AI стабильно ошибается на:

  • Gradle-конфигурации с flavors (Java 17 как минимум для Gradle 8.14+, баг с flutter_localizations)
  • Xcode-конвенции именования для iOS flavors (Debug-dev, Release-prod)
  • MethodChannel для нативных фич iOS/Android
  • Push notifications с FCM (разные пути для iOS и Android)

Каждый раз приходится править руками. AI-инструменты обучены на веб-стеке, где нет двух build-систем одновременно.

Integration-тесты с нативным UI

integration_test в Flutter не может взаимодействовать с нативными элементами: системные алерты, диалоги разрешений, WebView, любой UI от ОС. AI-инструменты генерируют integration-тесты, которые проходят в изоляции, но бесполезны для реальных user flows с permission-диалогами.

Для JourneyBay мы используем Maestro для E2E-тестов нативного UI. Claude Code пишет Maestro-YAML с ошибками (галлюцинации на незнакомом формате), но хотя бы знает, что проблема существует.

MCP-стек для Flutter-разработчика

Вот что стоит подключить в 2025-2026.

Dart MCP Server (официальный)

Появился в Dart SDK 3.9. Даёт AI-агенту прямой доступ к:

  • dart analyze - статический анализ в реальном времени
  • dart test - запуск тестов
  • dart format - форматирование
  • pub - управление зависимостями
  • Hot reload работающего приложения
  • Инспекция виджет-дерева запущенного приложения

AI генерирует код и тут же проверяет его. Цикл меняется: написал → проанализировал → поправил → запустил тесты. Всё в одной сессии.

DCM MCP Server

DCM (Dart Code Metrics) - 475+ правил качества кода для Flutter (181 в recommended-пресете). MCP-сервер позволяет AI запускать анализ и автофиксы:

AI генерирует код → DCM анализирует → DCM автоматически исправляет → dart format → DCM перепроверяет.

В 2025 году DCM добавил 93 новых правила и уменьшил потребление памяти на 91% (с 4 ГБ до 350 МБ для больших репозиториев). Это делает его практичным даже для крупных проектов.

Flutter Docs MCP

Отдельный MCP-сервер для документации Flutter и pub.dev. Даёт AI актуальные данные о пакетах, API, deprecated-методах. Частично решает проблему устаревших знаний.

Полный стек

На JourneyBay я использую параллельно:

  • Dart MCP - анализ, тесты, hot reload
  • Supabase MCP - база, миграции, edge functions
  • DCM MCP - качество кода
  • GitHub MCP - PR, issues
  • Linear MCP - задачи
  • Context7 MCP - документация библиотек

Шесть MCP-серверов. Claude Code работает в контексте всего проекта, а не одного файла. Об этом мало где пишут, а разница существенная.

Правила для CLAUDE.md: Flutter-специфика

Без CLAUDE.md AI генерирует generic-код. С ним - код под ваш проект. Вот что я добавил за полгода итераций (сейчас ~750 строк).

Обязательные секции

Архитектура:

Структура: features/<name>/{domain, data, presentation}
State: Riverpod + freezed для state classes
DI: get_it + injectable
Errors: Either<Failure, T> из dartz
Navigation: GoRouter

Запреты:

НЕ редактируй файлы *.freezed.dart, *.g.dart, *.config.dart
НЕ добавляй зависимости без разрешения
НЕ используй StatefulWidget для нового кода
НЕ добавляй ключи локализации в generated .dart - только в ARB

Кодогенерация:

После изменения @freezed, @injectable, @riverpod:
dart run build_runner build --delete-conflicting-outputs

Тестирование:

Все тесты через реальный production code path
Mock только внешние зависимости (API, DB)
AuthBridge - тестировать через testWidgets + AuthBridgeTestBed

UX-правила:

Text виджеты: maxLines + overflow
Row с текстом: Flexible/Expanded
Image: errorBuilder
Touch targets: минимум 44x44 dp
Новые экраны: SafeArea, keyboard-aware

Каждое правило появилось после конкретной ошибки. Не из книжки - из практики.

Правило для Flutter AI rules

Flutter-команда выпустила официальный rules.md в четырёх размерах (полный, 10K, 4K, 1K символов). Рекомендация: не копируйте его целиком. Длинные rules-файлы конкурируют с промптом за внимание модели и размывают результат.

Возьмите rules_4k.md как основу, добавьте специфику вашего проекта (стек, архитектуру, запреты), уберите generic-советы типа «используйте const где возможно». AI и так это знает. Ваш CLAUDE.md должен содержать то, что AI не может угадать.

Промпт-инжиниринг для Flutter: что работает

Указывайте слой архитектуры

Плохо: «Добавь функцию получения избранных мест»

Хорошо: «В domain/usecases/ создай GetFavoritePlaces use case. Принимает userId, возвращает Either<Failure, List>. Используй FavoritesRepository. Паттерн как в GetTripDetails.»

AI нужен контекст слоя. Без него он смешает data и domain, поместит HTTP-вызов прямо в use case.

Давайте файл-образец

«Создай провайдер для новой фичи. Образец: lib/features/trip/presentation/providers/trip_provider.dart. Следуй той же структуре.»

Claude Code прочитает образец и скопирует паттерн. Это работает лучше, чем описывать паттерн словами.

Разделяйте генерацию и build

«Создай модель, но НЕ запускай build_runner. Я запущу сам после проверки.»

Иначе AI редактирует → запускает build_runner → build_runner падает (потому что модель ещё не готова) → AI пытается «починить» → ломает ещё больше.

Для UI - описывайте constraints, не дизайн

Плохо: «Сделай красивую карточку места»

Хорошо: «Карточка места: фиксированная высота 120dp, изображение слева 80x80 с borderRadius 8 и errorBuilder, справа - title (maxLines: 2, overflow: ellipsis) и subtitle. Вся карточка - InkWell с минимум 44dp touch target.»

AI хорошо реализует спецификацию. С дизайном «на вкус» - хуже.

Слон в комнате: AI делает опытных разработчиков медленнее

Исследование METR (июль 2025, рандомизированное контролируемое испытание) показало: опытные open-source разработчики с AI-инструментами работают на 19% медленнее. При этом сами разработчики считали, что стали на 20% быстрее.

Разрыв между ощущением и реальностью - 39 процентных пунктов.

Объяснение: на знакомых репозиториях (1М+ строк, 22K+ звёзд) опытный разработчик уже знает, где что лежит. AI добавляет слой абстракции, который замедляет вместо ускорения. Время уходит на формулирование промптов, проверку результата, исправление галлюцинаций.

Но. Это верно для задач, где разработчик в контексте. Для задач «вне зоны» - новый стек, незнакомый API, тесты для чужого кода - AI ускоряет. Мой опыт это подтверждает: Claude Code экономит часы на задачах, где мне пришлось бы читать документацию. И тормозит на задачах, где я и так знаю ответ.

Для Flutter конкретно: AI ускоряет на boilerplate (модели, use cases, провайдеры) и тормозит на UI-вёрстке и архитектуре.

Ещё неприятная статистика

Qodo в отчёте за 2025 год измерил: AI-код содержит заметно больше логических ошибок и проблем безопасности по сравнению с кодом, написанным людьми. Faros AI обнаружил у команд с высоким adoption AI рост количества багов на 9% и увеличение размера PR на 154%.

По данным Stack Overflow 2025, 66% разработчиков жалуются, что AI-код «почти правильный» - компилируется, но работает не так.

При этом 84% разработчиков используют или планируют использовать AI-инструменты. Мобильные разработчики - на втором месте по adoption после фронтенда.

Цифры противоречивые. Большинство используют, но довольных меньше, чем хотелось бы.

Мой workflow: что я делаю сегодня

После полугода экспериментов у меня сложилась схема:

Claude Code делает:

  • freezed-модели, data classes, сериализацию
  • Use cases и domain-логику
  • Edge functions на Supabase
  • Рефакторинг через 10+ файлов
  • Unit и widget-тесты для domain/data слоёв
  • Миграции базы данных
  • Код-ревью через AI Concilium (параллельный опрос нескольких моделей)

Я делаю руками:

  • UI-вёрстку (Claude Code генерирует базу, я дорабатываю на устройстве)
  • Архитектурные решения (AI предлагает, я выбираю)
  • build_runner pipeline (контролирую руками)
  • Gradle/Xcode конфигурации
  • Проверку на реальных устройствах
  • Integration-тесты и E2E через Maestro

Соотношение: примерно 60% AI / 40% руками. Для веб-проекта, думаю, было бы 80/20. Flutter-специфика отъедает автоматизацию.

FAQ

Помогает ли указание версии Riverpod в промпте, если AI генерирует устаревшие паттерны?

Частично. Указание riverpod: ^3.0.0 снижает, но не устраняет устаревший код — обучающие данные модели по этой версии могут быть скудными. Надёжное решение — Context7 MCP или Flutter Docs MCP, которые подают актуальную документацию API во время генерации. Без живого источника документации следующий лучший вариант — добавить в CLAUDE.md пример корректного Riverpod 3.0 провайдера с Ref.mounted и mutations: модель скопирует продемонстрированный паттерн.

Каково реальное соотношение продуктивности у Flutter-разработчика с небольшим опытом и у опытного (2+ лет)?

Для разработчиков, только начинающих с Flutter, AI даёт прирост около 40–60% на boilerplate и настройке архитектуры — из-за отсутствия устойчивой ментальной модели проекта. Для опытных разработчиков на знакомых фичах применимо исследование METR: замедление на 19%, особенно на UI-вёрстке и архитектурных решениях. Точка перехода — примерно 6–12 месяцев опыта во Flutter: после этого AI максимально ценен на кросс-слойных задачах (рефакторинг, генерация тестов для незнакомых модулей), а не на фичах в хорошо изученных областях.

Как справляться с ошибками Gradle и Xcode, которые AI стабильно генерирует неправильно — есть ли безопасный подход к автоматизации?

Самый безопасный подход — полностью исключить Gradle и Xcode-конфиги из области ответственности AI и поддерживать их вручную или через платформо-специфичные инструменты. Если AI всё же нужен для конфигурационных изменений, используйте двухшаговый процесс: сначала попросите AI объяснить, что и почему нужно изменить, проверьте логику самостоятельно, затем примените изменение вручную. Никогда не позволяйте AI коммитить изменения Gradle или Xcode без локальной проверки сборки на обеих платформах. Ошибки в этих файлах приводили к многочасовым падениям CI даже в опытных командах.

Что делать прямо сейчас

  1. Настройте CLAUDE.md (или .cursorrules) с Flutter-спецификой вашего проекта. Не копируйте generic-правила - добавьте свою архитектуру, запреты, паттерны ошибок.

  2. Подключите Dart MCP Server (SDK 3.9+). AI, который может запустить dart analyze после генерации, ошибается на порядок реже.

  3. Добавьте DCM MCP Server для автоматической проверки качества.

  4. Не доверяйте AI UI-вёрстку без проверки. Генерируйте базу, тестируйте на 3+ размерах экрана.

  5. Разделяйте промпты по слоям архитектуры. AI работает лучше, когда задача локализована: «domain-слой, use case» работает лучше, чем «добавь фичу».

  6. Держите build_runner под контролем. AI не должен запускать кодогенерацию автоматически.

2.8 миллиона Flutter-разработчиков по данным на 2025 год. 45%+ кроссплатформенного рынка. А контента о том, как AI работает конкретно на этом стеке, до сих пор мало. Буду рад, если эта статья окажется полезной.