Вопросы на собеседовании: Flutter-разработчик
100 реальных вопросов с образцовыми ответами и пояснениями для уровня Junior Flutter-разработчик.
Смотреть пример резюме: Flutter-разработчик →Тренировка флешкарточками
Интервальное повторение · Hunter Pass
Вопросы
Они различаются моментом выбора типа и объёмом статических проверок Dart.
- var выводит один статический тип из инициализатора, поэтому после var count = 1 нельзя присвоить count строку.
- Object принимает любой объект Dart, кроме null, а Object? также принимает null, но оба требуют проверки типа перед обращением к его членам.
- dynamic откладывает проверки членов и присваиваний до выполнения, поэтому я оставляю его только на границах нетипизированных данных и быстро преобразую.
Зачем это спрашивают: Интервьюер проверяет, умеете ли вы пользоваться системой типов Dart, не отключая без необходимости статические проверки и null safety.
final присваивается один раз во время выполнения, а const обозначает константу времени компиляции.
- Значение final может прийти из DateTime.now() или ответа API, но после этого его нельзя переназначить.
- Значение const и всё содержимое его константной коллекции должны быть известны при компиляции.
- Экземпляры const-виджетов могут быть канонизированы и переиспользованы, поэтому я ставлю const у конструкторов, когда все аргументы постоянны.
Зачем это спрашивают: Сильный ответ отличает однократное присваивание от константы времени компиляции и связывает const с виджетами Flutter.
Типы Dart по умолчанию не допускают null, а nullable-тип нужно пометить знаком ?.
- String name не может содержать null, а String? name может, поэтому перед использованием значение нужно проверить или безопасно прочитать.
- ?? задаёт запасное значение, а ?. выполняет условный доступ; ! утверждает, что значение не равно null, и может вызвать ошибку при неверном утверждении.
- late откладывает инициализацию, но чтение до присваивания вызывает ошибку выполнения, поэтому я использую его лишь при гарантированном порядке жизненного цикла.
Зачем это спрашивают: Интервьюер оценивает, обрабатываете ли вы отсутствие значения явно, а не полагаетесь на небезопасные утверждения.
Я выбираю List для упорядоченных значений, Set для уникальных значений и Map для поиска по ключу.
- List сохраняет порядок и допускает повторы, что подходит для последовательности сообщений или товаров.
- Set удаляет повторы и даёт быстрые проверки наличия, например для ID выбранных категорий.
- Map получает значение по ключу, например userById[id], а collection if и for позволяют декларативно строить любую из этих коллекций.
Зачем это спрашивают: Интервьюер проверяет, умеете ли вы сопоставлять основные коллекции Dart с данными приложения.
Dart поддерживает необязательные позиционные и именованные параметры, а функции можно передавать и хранить как другие значения.
- Именованные параметры заключаются в фигурные скобки, а required отмечает обязательные, поэтому вызов createUser(name: 'Ana') легко читать.
- Необязательному параметру нужен nullable-тип или значение по умолчанию, а необязательные позиционные параметры заключаются в квадратные скобки.
- Callback типа VoidCallback можно передать кнопке, а короткую функцию из одного выражения записать через =>.
Зачем это спрашивают: Хороший ответ показывает синтаксис функций, который постоянно используется в конструкторах и callback-функциях Flutter.
Класс Dart объединяет состояние и поведение, а его конструкторы создают корректные экземпляры.
- Параметр this.name сразу инициализирует поле, а обязательные именованные параметры явно показывают необходимые входные данные.
- Именованный конструктор вроде User.guest() даёт ещё один понятный способ создания, а factory-конструктор может вернуть кэшированный экземпляр или подтип.
- extends переиспользует реализацию одного суперкласса, а переопределённые члены стоит отмечать @override, чтобы анализатор мог их проверить.
Зачем это спрашивают: Интервьюер проверяет практическое создание объектов и основы наследования, а не запоминание синтаксиса.
Интерфейс задаёт контракт для реализации, а mixin добавляет классам переиспользуемое поведение.
- Каждый класс Dart предоставляет неявный интерфейс, а implements требует реализовать все его члены в новом классе.
- interface class можно реализовать, но нельзя наследовать вне его библиотеки, что явно задаёт границу API.
- mixin подключается через with и позволяет делиться методами между несвязанными классами без глубокой цепочки наследования.
Зачем это спрашивают: Сильный ответ учитывает модификаторы классов Dart 3 и не путает mixin с контрактом интерфейса.
Records позволяют вернуть или объединить несколько типизированных значений без отдельного класса, а patterns распаковывают или проверяют их форму.
- Функция может вернуть (User, bool), сохранив типы обоих полей в статической системе типов.
- Деструктурирующее объявление final (user, cached) = result даёт имена полям record.
- List-, map-, object- и switch-паттерны извлекают вложенные значения, но для данных с идентичностью, методами или стабильной публичной моделью я использую именованный класс.
Зачем это спрашивают: Интервьюер проверяет знание современного синтаксиса Dart и умение не заменять им содержательные доменные модели.
sealed class задаёт закрытое семейство подтипов, которое switch может обработать исчерпывающе.
- Подтипы должны быть объявлены в той же библиотеке, поэтому компилятор знает полный набор.
- Loading, Success(data) и Failure(error) образуют практичную sealed-иерархию результата для экрана.
- Switch-выражение по такой иерархии выдаёт ошибку компиляции при пропущенном варианте, в том числе после добавления нового подтипа.
Зачем это спрашивают: Сильный ответ связывает sealed-типы с исчерпывающей обработкой состояний, а не представляет их синтаксической мелочью.
Future завершается один раз значением или ошибкой, а Stream может выдавать много значений со временем.
- Я ожидаю Future через await для одного ответа REST или чтения файла и ловлю ошибку через try и catch.
- Я подписываюсь на Stream для повторяющихся событий, например изменений авторизации или обновлений базы в реальном времени.
- Подписки Stream нужно отменять при dispose владельца, а await for может читать события до закрытия потока.
Зачем это спрашивают: Интервьюер проверяет, умеете ли вы выбирать и очищать основные асинхронные абстракции Dart.
Во Flutter метод build описывает UI для текущего состояния, а не отправляет команды для изменения отдельных представлений.
- При изменении состояния Flutter снова вызывает build и сопоставляет новую конфигурацию виджетов с существующим деревом.
- Флаг загрузки может прямо в дереве выбирать индикатор прогресса или содержимое.
- В build не должно быть сетевых вызовов и других побочных эффектов, поскольку фреймворк может вызывать его много раз.
Зачем это спрашивают: Интервьюер оценивает понимание модели от состояния к UI и умение сохранять build повторяемым.
Я использую StatelessWidget без изменяемого локального состояния и StatefulWidget, когда состояние должно сохраняться между пересборками.
- Объекты обоих виджетов неизменяемы; StatefulWidget создаёт отдельный изменяемый объект State.
- Заголовку только из аргументов конструктора подходит StatelessWidget, а локальному переключателю видимости пароля подходит StatefulWidget.
- Если состояние относится к нескольким экранам или бизнес-логике, я поднимаю его выше или переношу в слой управления состоянием, а не раздуваю локальный State.
Зачем это спрашивают: Сильный ответ знает, что сам StatefulWidget неизменяем, и хранит состояние в подходящей области.
Объект State инициализируется, может получать обновления зависимостей или виджета, пересобирается и в конце освобождается.
- initState запускается один раз для настройки без зависимости от inherited-виджетов, например для создания AnimationController.
- didChangeDependencies обрабатывает inherited-зависимости, а didUpdateWidget реагирует на новую конфигурацию виджета от родителя.
- dispose освобождает контроллеры, focus nodes и подписки перед вызовом super.dispose.
Зачем это спрашивают: Интервьюер проверяет, размещаете ли вы настройку, обновления и очистку в правильных методах жизненного цикла.
BuildContext определяет положение виджета в дереве элементов и служит для поиска предков вроде Theme или Navigator.
- Theme.of(context) ищет вверх именно из этой точки, поэтому нужный provider должен быть её предком.
- Context над только что созданным Scaffold не видит этот Scaffold; Builder может создать context под ним.
- После await я проверяю context.mounted перед навигацией или показом UI, потому что виджет могли удалить.
Зачем это спрашивают: Хороший ответ рассматривает context как положение в дереве и учитывает область предков и асинхронное время жизни.
Widgets являются неизменяемыми конфигурациями, elements управляют их смонтированной идентичностью, а render objects выполняют layout и отрисовку.
- build создаёт лёгкие описания widgets, которые можно заменять при каждой пересборке.
- Element связывает widget с позицией в дереве и сохраняет связанный State, пока совпадают тип и key.
- Экземпляры RenderObject получают constraints, выбирают размер, рисуют пиксели и выполняют hit testing для виджетов с рендерингом.
Зачем это спрашивают: Интервьюер проверяет, понимаете ли вы Flutter глубже фразы о том, что всё является виджетом.
Keys помогают Flutter сопоставлять конфигурации виджетов с существующими elements при изменении порядка или идентичности соседей.
- ValueKey(item.id) сохраняет правильный State при перемещении элементов в сортируемом списке.
- Keys важны среди соседей одного типа; случайные UniqueKeys принудительно теряют состояние вместо исправления идентичности.
- GlobalKey может обращаться к state или перемещать element по дереву, но он тяжелее и нужен лишь в случаях вроде FormState.
Зачем это спрашивают: Сильный ответ объясняет сохранение идентичности и не предлагает GlobalKey как стандартное решение.
Родитель передаёт constraints вниз, каждый ребёнок выбирает допустимый размер, а родитель размещает его.
- Constraints задают минимальную и максимальную ширину и высоту, а не всегда один точный размер.
- Ребёнок не может выйти за эти пределы, поэтому width 500 не переопределит максимум родителя в 300.
- Неограниченные constraints часто появляются внутри scrollables и конфликтуют с Expanded или ребёнком, который пытается занять бесконечное пространство.
Зачем это спрашивают: Интервьюер проверяет, можете ли вы объяснять типичное поведение layout через constraints, а не подбор размеров наугад.
Row и Column используют Flex layout, а Expanded и Flexible определяют, как дети делят оставшееся место по главной оси.
- Row располагает детей горизонтально, Column вертикально, а mainAxisAlignment распределяет свободное место на этой оси.
- Expanded использует tight fit и растягивает ребёнка на его долю flex, что может убрать переполнение текста в Row.
- Flexible по умолчанию использует loose fit и разрешает ребёнку занять меньше своей доли, а значения flex делят пространство пропорционально.
Зачем это спрашивают: Хороший ответ связывает Flex-виджеты с конкретной моделью переполнения и распределения пространства.
Для длинного или динамического списка я использую ListView.builder, чтобы создавать только видимые элементы и ближайший кэш.
- ListView с явным списком children сразу создаёт каждого ребёнка и подходит лишь для небольшого фиксированного списка.
- SingleChildScrollView создаёт всего ребёнка, поэтому оборачивание большой Column тратит память и время build.
- Для смешанных секций вроде app bar, grid и list CustomScrollView со slivers объединяет их в одну область прокрутки.
Зачем это спрашивают: Интервьюер оценивает понимание ленивого создания и умение избегать дорогих прокручиваемых layout.
MaterialApp предоставляет ThemeData для Material-виджетов, а CupertinoApp предоставляет CupertinoThemeData для виджетов в стиле iOS.
- Theme.of(context) и CupertinoTheme.of(context) читают унаследованные цвета и типографику вместо дублирования констант на каждом экране.
- ColorScheme позволяет Material-компонентам последовательно использовать роли primary, surface и error в светлой и тёмной темах.
- Я выбираю одну цельную дизайн-систему продукта и применяю платформенно-адаптивные элементы лишь там, где пользователи ожидают нативное поведение.
Зачем это спрашивают: Сильный ответ знает обе системы тем и не смешивает платформенные стили без продуктовой причины.
Закрытые вопросы
- 21
Как валидировать и отправить форму во Flutter?
formsfluttervalidation - 22
Как нужно управлять TextEditingController и FocusNode?
- 23
Когда использовать GestureDetector вместо InkWell?
interaction - 24
Как перейти на экран и вернуть результат во Flutter?
flutter - 25
Как добавить изображения и собственные шрифты в Flutter-приложение?
flutter - 26
Как сделать экран Flutter адаптивным?
responsiveflutter - 27
Как выглядит базовый процесс локализации во Flutter?
flutter - 28
Как обеспечить базовую доступность экрана Flutter?
flutter - 29
Когда использовать implicit animation во Flutter?
flutteranimation - 30
Что необходимо делать при использовании AnimationController?
animation - 31
Когда уместен setState и что он делает?
state - 32
Что означает lifting state up во Flutter?
flutter - 33
Когда использовать ValueNotifier и ValueListenableBuilder?
- 34
Как выглядит базовый поток Riverpod на экране Flutter?
flutterstate-management - 35
В чём основная идея BLoC во Flutter?
flutterstate-management - 36
Как вызвать REST API из Flutter-приложения?
restflutter - 37
Как преобразовать JSON-ответ в модель Dart?
dart - 38
Как Flutter-приложению обрабатывать сетевые ошибки и timeouts?
flutterresilience - 39
Какой вариант локального хранения выбрать во Flutter-приложении?
flutter - 40
Что нужно для добавления Firebase во Flutter-приложение?
flutter - 41
Для чего нужен pubspec.yaml в проекте Flutter?
yamlpackagesflutter - 42
Как оценить Flutter package перед добавлением?
decision-makingflutter - 43
Какой базовый Git-процесс вы используете для функции Flutter?
fluttergit - 44
Что делают dart analyze и dart format?
dart - 45
В чём разница между hot reload и hot restart?
tooling - 46
Чем режимы сборки Flutter отличаются от app flavors?
flutter - 47
Что такое unit-, widget- и integration-тесты во Flutter?
integrationintegration-testingflutter - 48
Как добавить и запросить мобильное permission во Flutter?
flutter - 49
Как Flutter-приложение может реагировать на изменения жизненного цикла?
reactflutter - 50
Для чего вы используете Flutter DevTools?
flutterflutter-devtools - 51
На узком телефоне Row показывает желто-черные полосы переполнения; как вы это исправите?
- 52
ListView внутри Column выдает ошибку неограниченной высоты; какое точное изменение вы внесете?
schema - 53
Экран создает 1000 карточек товаров в Column и зависает при открытии; как вы переделаете список?
schema - 54
HTTP-запрос завершается после ухода пользователя с экрана, и Flutter сообщает setState() called after dispose(); как это исправить?
flutterstatehttp - 55
Экран поиска создает TextEditingController, а его listener продолжает срабатывать после повторной навигации; что нужно очистить?
navigation - 56
После перестановки редактируемых задач введенный текст оказывается у другой задачи; как исправить keys?
- 57
FutureBuilder повторно загружает профиль при каждой перестройке родителя, и индикатор постоянно мигает; как это остановить?
async - 58
Сохранение завершается после закрытия страницы, а попытка показать SnackBar через context завершается ошибкой; что вы измените?
- 59
Форма входа отправляет невалидные поля без сообщений и оставляет клавиатуру поверх результата; как вы исправите этот сценарий?
forms - 60
Image.asset работает у одного разработчика, но в CI с учетом регистра появляется Unable to load asset; что вы проверите?
system-design - 61
REST-клиент пытается декодировать каждый ответ как JSON, падает на 204 и оставляет индикатор загрузки на 401; как вы обработаете статусы?
rest - 62
API иногда возвращает null в avatarUrl и не присылает address, из-за чего возникает ошибка приведения типа; как сделать парсинг безопасным?
fundamentals - 63
Запрос товаров может навсегда зависнуть при плохом соединении; как добавить timeout и восстановление?
resilience - 64
Лента на мгновение показывает Нет элементов, пока первый запрос еще загружается; как вы смоделируете экран?
- 65
При быстрой прокрутке страница 3 запрашивается дважды и появляются дубликаты товаров; как это исправить?
pagination - 66
Экран заметок должен показать последний успешно загруженный список, если телефон открыт без сети; какой базовый кэш вы добавите?
caching - 67
На ревью access token обнаружили в SharedPreferences; куда его перенести и что еще проверить?
tokens - 68
Вход через Firebase Auth проходит успешно, но после каждого перезапуска приложение на мгновение показывает экран входа; как это исправить?
- 69
Сообщения FCM видны в логах, пока приложение открыто, но пользователь не видит баннер; что вы реализуете?
- 70
Обновление заполненного каталога завершается ошибкой 500, и экран становится пустым; какой UI ошибки вы покажете?
- 71
Счетчик Riverpod меняется после нажатия кнопки, но подпись остается старой, потому что виджет использует ref.read; что вы измените?
widgetsstate-management - 72
ConsumerWidget выдает No ProviderScope found при открытии в widget-тесте; как исправить scope?
widgetsstate-management - 73
Двойное нажатие Сохранить отправляет два события BLoC и создает две записи; как это предотвратить?
state-management - 74
BLoC оформления заказа сбрасывается при каждом setState родителя, и введенные данные доставки исчезают; что вы проверите?
statestate-management - 75
Ввод в одном поле, похоже, перестраивает весь экран товаров на Riverpod; как это диагностировать и сократить?
state-management - 76
StreamSubscription состояния сети продолжает обновлять удаленный экран; как вы ее очистите?
streams - 77
Timer.periodic продолжает обновление после закрытия dashboard; какое точное исправление жизненного цикла нужно?
- 78
Декодирование JSON размером 5 МБ заметно замораживает прокрутку; как перенести эту работу с UI isolate?
concurrency - 79
Пользователь вводит cat, затем car, но более медленный запрос cat завершается последним и заменяет результаты car; как исправить гонку?
- 80
После ухода с экрана загрузка файла не останавливается, а поздний callback прогресса обращается к удаленному state; как добавить отмену?
resiliencecallbacks - 81
Widget-тест нажимает Отправить, но ожидаемый текст успеха не появляется, потому что UI ждет Future; как правильно вызвать pump?
widgets - 82
Golden-тест совпадает локально, но текст отличается в CI из-за другого шрифта; как его стабилизировать?
- 83
Widget-тест профиля обращается к настоящему staging API и падает без сети; как заменить эту зависимость?
widgetsapidependencies - 84
Как написать один integration-тест для входа и открытия экрана профиля?
integrationintegration-testing - 85
Отчет о production-баге содержит только request failed, а debug-логи печатают полные токены; как безопасно улучшить логирование?
tokensloggingbug-reporting - 86
После отказа в доступе к камере нажатие Сканировать ничего не делает; как обработать разрешения?
- 87
Android debug-сборка не обращается к локальному http API и сообщает cleartext traffic not permitted; что вы измените?
http - 88
iOS-приложение закрывается при открытии выбора фото, а консоль сообщает об отсутствующем usage description; как это исправить?
- 89
Открытие myapp://product/42 запускает приложение, но всегда показывает Home; как вы отладите deep link?
- 90
Таймер опроса продолжает отправлять запросы, пока приложение в фоне; как вы отреагируете на изменения жизненного цикла?
react - 91
После Git merge в pubspec.yaml и одном Dart-файле остались маркеры конфликта; как безопасно разрешить конфликт?
gityamlpackages - 92
flutter pub get падает, потому что package_a требует http ниже 1.0, а package_b требует http 1.x; что вы сделаете?
flutterhttp - 93
После добавления поля json_serializable сгенерированный part не содержит его, и компиляция падает; как обновить генерацию?
- 94
CI останавливается на flutter analyze из-за unawaited-вызова save, хотя при ручной проверке все работает; как это исправить?
fluttertesting - 95
Android release-сборку отклонили, потому что она подписана debug-сертификатом; что вы проверите?
- 96
Staging flavor по ошибке отправляет запросы в production; как разделить и проверить окружения?
- 97
Скринридер произносит кнопку удаления только как Кнопка, потому что на ней одна иконка; как сделать ее доступной?
a11y - 98
Телефонная компоновка растягивает одну текстовую колонку на весь 12-дюймовый планшет, и читать становится неудобно; как ее адаптировать?
schema - 99
Приложение показывает 1 items и использует английские правила в русском; как правильно локализовать количество?
- 100
На code review блок catch игнорирует ошибку запроса заказа, а finally всегда показывает Заказ оформлен; какой дефект вы отметите и исправите?
code-reviewdefects