Skip to content

Вопросы на собеседовании: Android-разработчик

100 реальных вопросов с образцовыми ответами и пояснениями для уровня Senior.

Смотреть пример резюме: Android-разработчик

Тренировка флешкарточками

Интервальное повторение · Hunter Pass

Вопросы

build-tools

Я выберу слоистую архитектуру по фичам и закреплю владение на уровне сборки:

  • Разделю каждую крупную фичу на :feature:<name>:api и :feature:<name>:impl, а небольшие связные фичи оставлю в одном модуле, пока данные о сборке не подтвердят необходимость разделения.
  • Помещу переиспользуемый UI в :core:designsystem, Android-сервисы в :core:platform, а чистые Kotlin-правила в :core:domain; фич-модули могут зависеть от внутренних core-модулей, но не от реализации соседней фичи.
  • Закреплю владельцев через CODEOWNERS, а правила зависимостей через собственный Gradle convention plugin и Dependency Analysis Gradle Plugin.
  • Приму дополнительные расходы на конфигурацию Gradle и API-обвязку, только если медианная инкрементальная сборка останется короче 30 секунд и обычное изменение фичи не потребует правок в реализации другой команды.

Зачем это спрашивают: Такая структура уравновешивает автономность команд и изоляцию сборки с реальной стоимостью поддержки 40 модулей.

dependencies

Я направлю зависимости от Android-деталей к стабильным Kotlin-контрактам:

  • presentation зависит от сценариев и моделей domain, domain не содержит импортов android.*, а data реализует интерфейсы репозиториев из domain.
  • Свяжу реализации только в корне композиции app через Hilt, используя @Binds в data-модулях и не раскрывая конкретные репозитории.
  • Добавлю Gradle-задачу на базе ArchUnit или Konsist, которая завершает сборку ошибкой при обратных связях, Android-импортах в domain или пути графа глубже 4 модулей.
  • Критерий приемки состоит в отсутствии циклов зависимостей в Gradle build scan; цена решения заключается в дополнительном преобразовании DTO, доменных и UI-моделей ради сохранения границ.

Зачем это спрашивают: Стабильные зависимости внутрь делают бизнес-правила тестируемыми, а автоматические проверки графа предотвращают размывание архитектуры.

roomapinetworking

Я оставлю контракт каждой функции минимальным, а :app сделаю единственным модулем, который знает о реализациях:

  • Помещу маршруты, объекты входных данных и результата и небольшой интерфейс FeatureEntry в :feature:<name>:api, используя только Kotlin и Parcelable, когда нужна передача между процессами.
  • Оставлю ViewModel, Compose-экраны, Room DAO, Retrofit-сервисы и Hilt-привязки в :feature:<name>:impl.
  • Подключу к :app все 8 impl-модулей и зарегистрирую реализации FeatureEntry в Hilt multibinding map, а потребители функций будут компилироваться только против api-модулей.
  • Приму один явный слой композиции и некоторое дублирование граничных моделей в обмен на проверку API, при которой Metalava не находит Room, Retrofit или impl-пакеты ни в одной публичной сигнатуре.

Зачем это спрашивают: Узкий контракт предотвращает утечку транзитивных технологий и позволяет независимо менять реализации функций.

architecture-patternsasyncconcurrency

Я выберу MVI, потому что оформление заказа представляет собой переходы конечного автомата:

  • Представлю все 5 шагов в одном неизменяемом CheckoutState и буду передавать типизированные CheckoutIntent в редьюсер ViewModel на Kotlin StateFlow.
  • Смоделирую 3 проверки как помеченные асинхронные результаты, чтобы устаревший ответ не перезаписал состояние после возврата пользователя или изменения ввода.
  • Сохраню в SavedStateHandle минимальные поля, текущий шаг и ожидающий effect ID оплаты; один ключ идемпотентности не даст восстановлению повторно отправить тот же платёж.
  • Цена решения состоит в большем объеме кода редьюсера и событий по сравнению с MVVM-привязками, и она допустима, только если тесты редьюсера покрывают каждый разрешенный переход, а пересоздание процесса восстанавливает все 5 шагов без повторной отправки платежа.

Зачем это спрашивают: MVI делает историю переходов оформления заказа детерминированной, что напрямую выполняет требования к точному восстановлению и обработке параллельных операций.

roomendpointsarchitecture

Я оставлю правила поиска на границе domain, а весь ввод-вывод скрою за контрактами репозитория:

  • Определю SearchRepository и SearchUseCase в чистом Kotlin-модуле :search:domain с доменными моделями Query и Result, без типов Android, Room или Retrofit.
  • Реализую выбор эндпоинта, преобразование DTO и координацию кеша Room в :search:data с помощью Retrofit, Room и kotlinx.coroutines.
  • Оставлю состояние Compose, задержку debounce и пользовательские события в :search:presentation, вызывая только SearchUseCase из ViewModel, внедренной через Hilt.
  • Приму три представления моделей как цену изоляции; критерий приемки состоит в том, что тесты :search:domain выполняются Gradle-задачей JVM test, а реализации обоих эндпоинтов или кеша заменяются без изменений presentation.

Зачем это спрашивают: Эти границы отделяют правила поиска от транспорта и хранилища, сохраняя быструю проверку на JVM.

monolith

Я буду разделять монолит по измеренным границам зависимостей, а не переносить сразу все пакеты:

  • Использую анализ зависимостей Android Studio и Dependency Analysis Gradle Plugin для построения карты циклов, затем ранжирую 24 функции по связанности, стоимости сборки и частоте изменений.
  • В релизах 1 и 2 извлеку общие Kotlin domain-модули и design system, затем в каждом релизе перенесу по 4 слабосвязанные функции за явные интерфейсы.
  • В релизах с 3 по 6 перенесу оставшиеся функции через адаптер branch by abstraction, чтобы старый и извлеченный код могли сосуществовать без параллельного продуктового поведения.
  • Приму временные адаптеры и дублирование моделей, но потребую, чтобы каждый релиз сокращал число строк в :app, не добавлял циклов в Gradle build scan и проходил существующий набор Android instrumentation-тестов.

Зачем это спрашивают: Пошаговое извлечение ограничивает риск релиза, а измеримые цели по графу и строкам доказывают реальное сокращение монолита.

Я выберу dynamic feature с загрузкой по требованию только после проверки задержки доставки относительно лимита в 5 секунд:

  • Помещу UI сканера и нативные библиотеки в модуль Play Feature Delivery с dist:onDemand=true, а его небольшой навигационный контракт оставлю в базовом приложении.
  • Запущу предварительную загрузку через SplitInstallManager после сигнала о намерении открыть сканер, покажу прогресс в байтах и обработаю отмену, нехватку места и ошибки доставки Play Store.
  • Измерю p95 времени от начала установки до открытия и размер нативных библиотек через Play Console и Firebase Performance на типичных устройствах в сети 4G.
  • Цена решения состоит в меньшей базовой загрузке для 92 процентов пользователей при зависимости входа от сети; выпущу функцию динамически, только если p95 первого запуска не превышает 5 секунд, иначе включу ее в базовую поставку или уменьшу ресурсы сканера.

Зачем это спрашивают: Решение привязано к измеренной доставке, а не к предположению, что крупную редко используемую функцию всегда нужно загружать по требованию.

composemigrationsjetpack

Я буду переносить по одной функциональной границе и сохраню независимость навигационных контрактов от UI-инструментария:

  • Размещу корневые Compose-экраны новых функций в контейнерах Fragment через ComposeView и буду использовать ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed в смешанный период.
  • Раскрою из API-модулей функций только типизированные контракты назначения и результата; XML Fragment и адаптеры Compose NavHost будут локально преобразовывать эти контракты.
  • Перенесу общие цвета, типографику, интервалы и тестовые теги в Compose design system, сохранив псевдонимы XML-ресурсов, пока ими пользуется хотя бы один из 90 устаревших экранов.
  • Приму временную совместимость Fragment и тем на 4 релиза при условии, что после переноса каждой функции маршруты не меняются, сохраненное состояние не регрессирует, а запуск с baseline profile отличается не более чем на 5 процентов.

Зачем это спрашивают: Граница на уровне функции локализует код совместимости и не привязывает публичную навигацию ни к XML, ни к Compose.

Я опубликую типизированные навигационные контракты из API-модулей функций и разрешу их в оболочке приложения:

  • Задам каждому назначению Kotlin-маршрут с @Serializable и явные типы входа и результата в его :api-модуле, не раскрывая Fragment, NavController или классы Compose-экранов.
  • Зарегистрирую обработчики маршрутов из всех 14 реализаций через Hilt multibindings, а конкретную привязку назначений оставлю графу Navigation Compose на уровне приложения.
  • Сопоставлю 6 проверенных App Links с теми же типизированными маршрутами в одном парсере, проверю хосты через assetlinks.json и протестирую ссылки командой adb am start.
  • Приму централизованную сборку графа как цену изоляции; Gradle-граф должен содержать ноль связей impl-to-impl, а контрактные тесты должны разрешать все 14 регистраций и все 6 ссылок.

Зачем это спрашивают: Типизированные маршруты на уровне API развязывают реализации функций и сохраняют единый проверяемый вход для внутренней и внешней навигации.

configbuild-tools

Сначала я зафиксирую разрешенный граф в коде, затем оптимизирую конфигурацию и выбор задач по измерениям build scan:

  • Определю типы модулей и разрешенные связи в Kotlin Gradle convention plugins и буду останавливать CI, если поиск циклов алгоритмом Тарьяна обнаружит любой из текущих 9 циклов или запрещенную связь между функциями.
  • Устраню циклы, извлекая минимальные стабильные контракты в api-модули или чистые Kotlin-модули, и не буду маскировать связь через compileOnly или рефлексию времени выполнения.
  • Включу configuration cache, параллельное выполнение и type-safe project accessors, затем с помощью Gradle Enterprise build scans и Dependency Analysis Gradle Plugin удалю ненужные api-зависимости.
  • Приму дополнительную поддержку convention plugins в обмен на ноль циклов, конфигурацию не дольше 25 секунд и CI-сборку затронутых модулей быстрее 12 минут в 95 процентах запусков.

Зачем это спрашивают: Исполняемые правила графа предотвращают регрессии, а отдельные временные критерии показывают, улучшает ли модульность сборку, а не просто переставляет ее части.

validationarchitecture-components

Я бы оставил одного владельца долгоживущего состояния экрана, а детям передал только нужные данные и события:

  • Определить на границе экрана неизменяемый ProfileEditorState с 6 значениями, 6 nullable-ошибками полей и статусом сохранения, затем отдавать его из ViewModel через StateFlow.
  • Передавать каждой секции небольшой неизменяемый срез и типизированные колбэки вроде onNameChanged, а не ViewModel или сеттеры MutableState.
  • Вычислять баннер и saveEnabled из канонических значений полей у владельца, чтобы дочерние компоненты не создавали противоречивое состояние валидации.
  • Локально хранить только краткоживущие детали интерфейса, например фокус и открытую клавиатуру, а правки и прогресс сохранения поднять выше для переживания смены конфигурации.

Зачем это спрашивают: Такое разделение дает экрану единый источник истины и сохраняет дочерние composable-функции переиспользуемыми и stateless.

resilience

Я бы направил состояние вниз одним потоком, а все действия пользователя возвращал через одну точку приема событий:

  • Представить 4 состояния отрисовки исчерпывающей sealed-иерархией и отдавать из ViewModel один StateFlow<CheckoutUiState>.
  • Отправлять все 5 типов событий в onEvent, а работу с репозиторием и последовательное обновление состояния выполнять внутри ViewModel, не меняя состояние из composable-функций.
  • Отрисовывать состояние через collectAsStateWithLifecycle и исчерпывающий when, передавая 12 строкам корзины только неизменяемые модели и колбэки.
  • Представить успешную оплату долгоживущим состоянием PaymentCompleted(transactionId), которое определяет переход к чеку, а отдельный SharedFlow оставить только для toast, потеря которых допустима.

Зачем это спрашивают: Долгоживущее завершение оплаты сохраняет обязательный переход после перезапуска сбора, а необязательная обратная связь остаётся вне состояния экрана.

Я бы сначала получил воспроизводимые измерения и только потом менял аннотации или структуры данных:

  • Включить метрики и отчеты Compose compiler для сборки, близкой к release, затем проверить фактическую стабильность и skippability параметров ленты и карточки с текущими настройками компилятора проекта.
  • Снять счетчики рекомпозиций в Layout Inspector по фиксированному сценарию из 10 обновлений избранного и 3 изменений панели, повторив запуск 3 раза из одинакового начального состояния.
  • Исправить только измеренную причину: использовать неизменяемые модели карточек, сохранять экземпляры неизменившихся элементов и передавать стабильные колбэки, добавляя @Immutable лишь при выполнении контракта всеми свойствами.
  • Повторить те же 3 запуска и записать разницу, ожидая обновления измененной карточки и панели при сохранении skippability остальных видимых карточек и в отчете, и в счетчиках.

Зачем это спрашивают: Данные компилятора и контролируемые счетчики рекомпозиций отделяют реальную нестабильность от безвредного выполнения родительской функции.

snapshotoop

Я бы последовательно применял записи у одного владельца состояния и публиковал каждый узел как неизменяемое значение:

  • Хранить 40 неизменяемых NodeUi в SnapshotStateList, а selectedNodeId в отдельном snapshot state, передавая детям данные только для чтения и функции событий.
  • Направлять фоновые обновления через канал в reducer главного потока, затем один раз заменять нужный NodeUi сразу со всеми 3 измененными полями внутри одного блока Snapshot.withMutableSnapshot.
  • Проводить события перетаскивания через тот же reducer, чтобы записи геолокации и жестов имели определенный порядок и не меняли список из двух потоков.
  • Не менять свойства внутри NodeUi и не модифицировать список во время обхода, поскольку замена одного элемента по индексу дает Compose точную границу snapshot-инвалидации.

Зачем это спрашивают: Неизменяемые элементы и последовательные атомарные записи позволяют каждой композиции читать согласованный snapshot без полной замены списка.

lifecyclecallbacks

Я бы задавал ключи каждого эффекта по тем ресурсам, смена идентичности которых требует отмены или очистки:

  • Использовать LaunchedEffect(itemId) для потока текущего элемента, чтобы при смене 101 на 102 старый сбор отменялся до запуска нового эффекта с другим ключом.
  • Использовать DisposableEffect(lifecycleOwner, itemId), регистрировать единственный observer и удалять именно его в onDispose при смене любой идентичности или выходе composable-функции из композиции.
  • Обернуть onExpired в rememberUpdatedState и вызывать полученное состояние из observer, чтобы новый колбэк применялся без перезапуска эффектов.
  • Проверить последовательность 101, 102, 103, утверждая наличие не более 1 активного коллектора и 1 observer после каждой смены, а после disposal ровно 0 обоих.

Зачем это спрашивают: Ключи идентичности управляют временем жизни ресурсов, а rememberUpdatedState обновляет поведение без лишних перезапусков.

indexessnapshot

Я бы использовал derived state для отрисовки, а snapshot flow для suspend-эффекта:

  • Создать один remembered LazyListState и запомнить derivedStateOf, который вычисляет listState.firstVisibleItemIndex > 5 для видимости кнопки.
  • Читать в композиции только этот Boolean, чтобы прокрутка между индексами по одну сторону порога не инвалидировала кнопку.
  • В LaunchedEffect(listState) собирать snapshotFlow { listState.firstVisibleItemIndex > 5 }.distinctUntilChanged().drop(1).filter { it } и отправлять аналитику из коллектора.
  • Не выполнять аналитику в derivedStateOf или композиции, поскольку переход false в true в потоке уже создает ровно 1 событие на каждое пересечение порога вверх.

Зачем это спрашивают: Производное значение ограничивает инвалидацию интерфейса, а snapshotFlow превращает snapshot-чтения в поток событий без повторов.

uischema

Я бы не принимал решения о размерах во время композиции и выполнил весь адаптивный алгоритм внутри Layout:

  • На фазе композиции создать те же 6 дочерних карточек в семантическом порядке, не читая размер родителя и не сохраняя измеренные размеры в состоянии.
  • На фазе измерения выбрать 1 или 2 колонки по maxWidth, вычесть зазор 16 dp для 2 колонок, один раз измерить каждый дочерний элемент с фиксированной шириной колонки и определить высоту строки по самому высокому дочернему элементу.
  • Ограничить сумму высот строк и вертикальных зазоров constraints родителя, затем вернуть итоговые ширину и высоту из layout.
  • На фазе размещения использовать placeRelative с рассчитанными смещениями строк для поддержки RTL, а разделители рисовать через drawWithContent без повторного измерения дочерних элементов и изменения состояния.

Зачем это спрашивают: Разделение композиции, однопроходного измерения, относительного размещения и рисования соблюдает требования к адаптивной геометрии и фазам.

css

Я бы отделил идентичность элемента от позиции и согласовал границы переиспользования с 3 видами разметки:

  • Вызвать items с глобально уникальным стабильным ключом, например тип плюс backend ID, и не использовать индекс, чтобы добавление 20 сообщений в начало сохраняло идентичность и видимый якорь.
  • Возвращать из contentType ровно header, message или ad, чтобы LazyColumn переиспользовал слоты композиции только между структурно совместимыми строками.
  • Поднять один nullable expandedMessageId в состояние экрана и вычислять expanded каждой строки по стабильному ID, не запоминая раскрытие по позиции.
  • Проверить тестом добавление 20 сообщений при видимой и раскрытой строке в середине, затем убедиться, что тот же ID остался якорем и единственным раскрытым элементом.

Зачем это спрашивают: Стабильная идентичность сохраняет состояние строки при вставке, а content types предотвращают несовместимое переиспользование слотов.

designconcurrency

Я бы использовал одно долгоживущее состояние экрана для обеих адаптивных компоновок и сохранял только компактный пользовательский ввод:

  • Определять компоновку из 1 или 2 панелей по текущей ширине окна при каждом layout, при этом обе версии читают общие selectedConversationId, filter и draft.
  • Хранить эти 3 saveable-значения в SavedStateHandle у ViewModel, а 60 переписок заново загружать из репозитория, не помещая модели строк в saved state.
  • В компактном режиме переходить между списком и деталями по selectedConversationId, а в расширенном показывать обе панели и тот же выбор без копирования состояния между composable-функциями.
  • Проверить ширины 412 dp и 1 200 dp, затем пересоздать Activity и восстановить ViewModel из saved state, подтвердив возврат всех 3 значений и загрузку строк из репозитория.

Зачем это спрашивают: Общее долгоживущее состояние сохраняет пользовательский выбор при смене размера и пересоздании процесса без превышения лимитов saved state.

formsuicompose

Я бы заменил 2 выбранные области за четкими границами и сохранил одного владельца состояния для всех 4 областей:

  • Разместить ComposeView в каждой переносимой позиции XML и задать DisposeOnViewTreeLifecycleDestroyed, чтобы обе композиции удалялись вместе с lifecycle представления Fragment.
  • Собирать существующее состояние ViewModel внутри Compose с учетом lifecycle и отправлять события промокода и оплаты обратно в тот же ViewModel, не создавая второй источник истины.
  • Оставить toolbar и RecyclerView с 12 строками без изменений в релизе 1; если внешняя оболочка позже перейдет на Compose, разместить RecyclerView через AndroidView с однократным factory, идемпотентным update и очисткой в onRelease.
  • Сохранить общие insets, порядок фокуса, accessibility labels и стабильные test ID на границах Views и Compose, затем проверить пересоздание с ровно 1 активным коллектором на каждую перенесенную область.

Зачем это спрашивают: Привязанная к lifecycle композиция и общее состояние позволяют перенести две области без обязательной переделки навигации или списка.

Закрытые вопросы

  • 21

    Лента с изображениями работает при лимите heap 256 МБ. Android Studio Memory Profiler показывает 118 МБ после запуска и 232 МБ после пяти циклов открытия и закрытия, а LeakCanary удерживает один FeedActivity через callback адаптера. Составьте план работы с памятью, включая кеш миниатюр для 400 элементов.

    cachingmemorycallbacks
  • 22

    После нажатия интерфейс иногда зависает на 6,2 секунды, пока Room читает 18 000 строк и преобразует их в JSON в главном потоке. Трасса близка к 5-секундному порогу input-dispatch ANR в Android. Как вы диагностируете и переработаете этот путь?

    roomconcurrencyanr
  • 23

    Экран с прокруткой рендерит кадры за 12 мс по медиане, но за 24 мс на p95 на телефоне с 60 Гц, а на телефоне со 120 Гц ощущается ещё хуже. Объясните бюджеты и предложите исследование рывков с целями для обоих дисплеев.

    rendering
  • 24

    Холодный запуск занимает 1,45 секунды на p50 и 2,10 секунды на p95 на эталонном телефоне с API 28, а требование продукта задаёт p95 ниже 1,20 секунды. Приложение инициализирует пять SDK в Application.onCreate. Как вы измерите и сократите запуск?

    api
  • 25

    После очистки пути запуска холодный старт release-сборки всё ещё занимает 1,30 секунды на p95 при CompilationMode.None. Можно добавить Baseline Profile, но рост APK должен остаться ниже 1,5 МБ, а улучшение нужно доказать на API 28 и API 34. Что вы реализуете?

    api
  • 26

    Compose LazyColumn с 1 000 строками разных типов пропускает 14% кадров при быстром скролле и выделяет 6 МБ памяти в секунду. Каждая строка создаёт форматтер валюты и получает изменяемый элемент, статус которого меняется каждую секунду. Как вы оптимизируете список без устаревшего UI?

    composeoptimization
  • 27

    Экран оформления запускает запросы цены, остатков и доставки, каждый длится до 800 мс. Ошибка остатков должна отменять доставку, при ошибке цены можно показать кеш, а вся работа должна остановиться при очистке ViewModel. Как вы структурируете корутины?

    architecture-componentscachingcoroutines
  • 28

    Suspend-метод репозитория разбирает JSON-ответ размером 12 МБ за 420 мс и записывает 6 000 строк в Room, а вызывающие стороны запускают его из Dispatchers.Main. UI может тратить на эту операцию не более 8 мс за кадр. Где должны находиться границы dispatcher?

    coroutinesroom
  • 29

    Пользователь может отменить импорт 50 000 записей. Разбор идёт циклами по 2 000 записей, сейчас отмена занимает 3,4 секунды, а отменённый запуск иногда фиксирует последнюю транзакцию Room. Переработайте отмену с целевой задержкой 150 мс.

    transactionsroombatch
  • 30

    Flow датчика выдаёт 200 измерений в секунду, отрисовка может обработать 30 в секунду, а коллектору отправки на сервер нужны все измерения пачками по 100. UI должен показывать данные не старше 100 мс, при этом потери при загрузке должны быть нулевыми. Как вы обработаете backpressure?

    batchbackpressureconcurrency
  • 31

    Репозиторий выдаёт 20 обновлений цены в секунду, двум UI-подписчикам после каждого поворота нужен последний результат, а аналитика должна получать только события, выпущенные во время её подписки; где вы примените холодный Flow, StateFlow и SharedFlow?

    coroutines
  • 32

    У экрана поиска 3 подписчика, пользователи обычно уходят с него на 3 секунды, но могут вернуться через 30 минут, а перезапуск холодного источника занимает 800 мс; как вы настроите для stateIn или shareIn политику запуска, replay и тайм-ауты?

    resilienceconfig
  • 33

    Результат оплаты приходит во время 2-секундного отсутствия подписчика Fragment при пересоздании, а навигация должна выполниться один раз без потери или повтора; как вы доставите этот одноразовый эффект?

    android-components
  • 34

    Приложению нужны один Retrofit-клиент на процесс, состояние оформления заказа для 3 ViewModel после 2 поворотов, отдельный экземпляр репозитория для каждой ViewModel и Activity-хелпер, пересоздаваемый при каждом повороте; какие scope Hilt подходят?

    android-componentsarchitecture-componentsdependency-injection
  • 35

    В 4 Gradle-модулях :app, :feature-checkout, :core-network-api и :core-network-impl фича видит NetworkClient, но Hilt сообщает об отсутствующей привязке; как организовать зависимости и видимость графа?

    dependenciesbuild-toolsapi
  • 36

    Шесть обработчиков команд поступают из 3 feature-модулей, а кеш авторизованной сессии должен быть общим для 3 Activity в течение 45-минутной сессии и очищаться при выходе; как совместить multibindings с собственным session-компонентом Hilt?

    componentscachingsessions
  • 37

    В приложении есть откладываемая 2-минутная синхронизация, немедленная отправка 800 МБ на сервер по действию пользователя длительностью около 12 минут и календарное напоминание, которое должно сработать в 08:00; когда использовать WorkManager, foreground service и точный будильник?

    android-componentsjetpackalerting
  • 38

    Для резервной копии размером 15 МБ нужны безлимитная сеть, зарядка и минимум 20 процентов батареи, но продукт требует завершения за 6 часов, хотя устройство может перейти в Doze, а приложение попасть в бакет Rare; как вы запланируете работу?

    backups
  • 39

    Три одинаковых запуска отправки на сервер приходят за 10 секунд, сервер может зафиксировать результат до тайм-аута клиента, а операция допускает не более 5 повторов; как совместить unique work, backoff и идемпотентность?

    resilienceidempotency
  • 40

    Дашборд требует фонового обновления каждые 5 минут, периодическая работа допускает flex-окно 5 минут, а обновление по действию пользователя должно начаться в течение 10 секунд даже при исчерпанной expedited-квоте; что вы реализуете?

  • 41

    У вас есть публичный inline reified маппер, который используется в 18 местах в 3 feature-модулях Android, а release APK может вырасти не более чем на 24 КБ; как вы ограничите размер кода и сохраните ABI-совместимость для внешних вызовов?

  • 42

    Редьюсер экрана обрабатывает 9 действий и 5 состояний, а каждое новое действие должно вызывать ошибку компиляции, пока его явно не обработают; как вы смоделируете sealed-иерархию и редьюсер без ветки else?

  • 43

    Fragment использует 3 делегата свойств для ViewBinding, аргументов навигации и кэша изображений размером 6 МБ; при ограничении жизненного цикла представления Fragment какой владелец и когда должен очищать каждое значение?

    android-componentslifecyclecaching
  • 44

    Вы хотите представить UserId как Kotlin value class над String, но он пересекает 2 Java API, Parcelable-аргументы навигации и JSON-сериализатор, которому нужна стабильная строка в wire-формате; как вы определите границы?

    serializationapikotlin
  • 45

    Спроектируйте Kotlin API, который копирует элементы из read-only producer в mutable consumer для Animal, Cat и Dog, принимая List<Cat> и MutableCollection<Animal>; какие ограничения вариантности обобщённых типов и контрактные тесты вы используете?

    contractgenericskotlin
  • 46

    В приложении есть 6 dynamic feature-модулей и 12 типизированных destination, включая HTTPS deep link в модуль, который может быть не установлен; как вы определите владение маршрутами и проверите ссылку без передачи NavController?

    ownershiphttpsvalidation
  • 47

    Checkout на Compose из 4 шагов должен переживать смерть процесса, но SavedStateHandle и rememberSaveable вместе должны укладываться в бюджет Bundle 200 КБ; что вы сохраните, если корзина содержит 80 позиций?

    composeconcurrency
  • 48

    Flow сразу выдаёт Loading, затем Data через 5 секунд и Error после задержки повтора в 2 секунды; как вы протестируете все 3 значения с runTest, TestDispatcher и Turbine, не ожидая 7 реальных секунд?

    resilience
  • 49

    В Compose-форме есть 7 полей, 2 сообщения валидации и кнопка отправки, а состояние должно восстанавливаться после пересоздания Activity; как вы протестируете семантику и восстановление без привязки к позиции текста?

    formscomposevalidation
  • 50

    Для приложения с 14 Gradle-модулями определите пирамиду тестов CI с бюджетом 8 минут на pull request, 25 минут на nightly и ровно 2 моделями физических устройств, включая Macrobenchmark и gate для Baseline Profile.

    pyramidbuild-tools
  • 51

    После релиза 8.14 Play Console показывает 1,34% пользовательских ANR при медиане аналогичных приложений 0,42% и место в худших 8% категории; трассировка input dispatch показывает runBlocking в главном потоке 5,48 с, пока Room сканирует 186 000 строк и выполняет checkpoint WAL. Это проблема базы, корутин или рендеринга, и какое исправление с регрессионным порогом вы выберете?

    databaseroomincidents
  • 52

    Play Console показывает рост ANR с 0,18% до 0,91%, место в худших 15% и 73% кластеров Input dispatching timed out после нажатия на настройки; Perfetto показывает 6,24 с в FileInputStream.read и разборе JSON-кеша размером 38 МБ в главном потоке. Нужно исправлять файловую систему, подавлять кластер или менять путь обработки действия?

    caching
  • 53

    Версия 5.6 достигает 0,76% пользовательских ANR при медиане 0,29% и попадает в худшие 11%; трассировки показывают блокировку главного потока на 5,87 с синхронным Binder-вызовом к PackageManager при открытии выбора приложения с 412 установленными пакетами. Следует повторить Binder-вызов, кешировать результат или перенести вызов?

    resiliencecaching
  • 54

    После включения live sync Play Console сообщает о 1,08% ANR при медиане 0,36% и месте в худших 6%; трассировка показывает ожидание synchronized(SessionStore) главным потоком 5,63 с, пока владеющий монитором SyncWorker выполняет HTTPS-чтение 5,71 с. Исправлять нужно тайм-аут, коллекцию или границу блокировки?

    sessionshttpsmonitoring
  • 55

    После обновления приложения manifest BroadcastReceiver для ACTION_MY_PACKAGE_REPLACED повышает ANR в Play Console с 0,22% до 0,84%, помещает приложение в худшие 13% и даёт трассировки, где onReceive выполняет миграцию токена и синхронное обновление в главном потоке 6,41 с. Если тайм-аут receiver может быть больше, оставить работу там, использовать goAsync или запланировать её отдельно?

    resilienceandroid-componentsmigrations
  • 56

    В релизе 11.2 доля ANR равна 0,69% при медиане 0,21%, а приложение попадает в худшие 9%; нажатие «Развернуть все» на Compose-экране с 9 800 элементами вызывает input timeout 5,36 с, включая 4,72 с разбора Markdown внутри composition и 0,64 с measure и layout. Оптимизировать парсер, виртуализировать UI или перенести создание состояния?

    composeuioptimization
  • 57

    На Pixel 7 с экраном 60 Гц прокрутка ленты дает 18,6% медленных кадров при бюджете 16,67 мс; Macrobenchmark FrameTimingMetric показывает p95 41,2 мс, JankStats отмечает bind image-card, Perfetto фиксирует декодирование bitmap в главном потоке по 28-44 мс, а Compose tracing почти не показывает лишней recomposition. Настраивать Compose, предзагрузку данных или изображения?

    composeconcurrency
  • 58

    На Galaxy S25 с экраном 120 Гц список контактов Compose дает 31,4% медленных кадров при бюджете 8,33 мс; FrameTimingMetric показывает p95 19,6 мс, JankStats отмечает contact-row, Compose tracing показывает recomposition всех 42 видимых строк при одном выборе, а Perfetto не находит узкого места GPU. Снижать частоту, оптимизировать рисование или менять состояние и стабильность?

    trackingoptimizationcompose
  • 59

    Список поиска на экране 60 Гц после добавления значков сохранения ухудшился с 3,1% до 12,7% медленных кадров; FrameTimingMetric показывает p95 27,8 мс, JankStats отмечает result-row, Perfetto фиксирует запрос Room по 10-22 мс при каждом bind, а Compose tracing показывает стабильные строки. Добавлять индекс, переносить каждый запрос из главного потока или устранять запросы для строк?

    indexesqueriesroom
  • 60

    На устройстве 120 Гц сворачивание заголовка Compose дает ровно 22,9% медленных кадров при бюджете 8,33 мс; FrameTimingMetric показывает p95 17,4 мс, JankStats отмечает header-collapse, Perfetto фиксирует measure и layout по 9-14 мс в кадре, а Compose tracing связывает это с анимацией высоты. Оптимизировать шейдер, ограничить 60 Гц или изменить примитив анимации?

    composeuioptimization
  • 61

    На Pixel 6 с экраном 60 Гц лента RecyclerView из 200 строк показывала 18,6% медленных кадров, P95 времени кадра 42,3 мс и 7,8 МБ аллокаций за один быстрый скролл. Perfetto показывал повторные измерения и bind на главном потоке. Как вы нашли и исправили проблему?

    uiconcurrency
  • 62

    На Galaxy S22 с экраном 120 Гц Compose LazyVerticalGrid показывал 24,9% медленных кадров, P95 времени кадра 31,6 мс и 11,4 МБ аллокаций при прокрутке 300 карточек. Compose tracing показывал широкую рекомпозицию на каждом шаге прокрутки. Что вы изменили?

    compose
  • 63

    На Galaxy S24 с экраном 120 Гц скролл экрана товара даёт 29,6% медленных кадров и P95 21,7 мс при бюджете 8,33 мс. Perfetto показывает завершение GPU за 14-23 мс, а визуализация overdraw в HWUI показывает 5,4-кратную перерисовку в местах пересечения полупрозрачных затемнений, скруглённых накладок и теней. Composition, measure, layout и декодирование изображений в главном потоке укладываются в 4,1 мс. Как вы нашли и исправили проблему?

    concurrencyoopdataviz
  • 64

    На Pixel 4a с лимитом heap приложения 256 МБ после 30 переходов Dashboard -> Scanner -> назад heap вырос с 74 до 181 МБ, а PSS со 128 до 246 МБ; приложение падало по OOM примерно на 224 МБ heap. LeakCanary нашёл 30 удерживаемых ScannerActivity через callback singleton. Что вы исправили?

    callbacksdata-structures
  • 65

    На Galaxy A52 с лимитом heap 256 МБ после 40 открытий и закрытий Fragment с деталями заказа heap вырос с 61 до 169 МБ, а PSS со 116 до 231 МБ; OOM происходил примерно на 218 МБ heap. LeakCanary нашёл 40 удерживаемых деревьев View через listener адаптера. Как вы устранили утечку?

    uidata-structuresandroid-components
  • 66

    На Pixel 7 с лимитом heap 384 МБ после 35 входов и выходов из checkout на Compose heap вырос с 92 до 207 МБ, а PSS со 154 до 283 МБ; в длинном прогоне процесс падал по OOM примерно на 338 МБ heap. LeakCanary нашёл 35 удерживаемых владельцев ComposeView через платёжный callback. Что вы исправили?

    concurrencycallbacksdata-structures
  • 67

    На Redmi Note 10 с лимитом heap 192 МБ после 25 переходов через SearchFragment heap вырос с 58 до 146 МБ, а PSS со 109 до 205 МБ; OOM начинался примерно на 171 МБ heap. LeakCanary нашёл 25 удерживаемых фрагментов через coroutine, собиравшую обновления геолокации. Как вы исправили и доказали результат?

    data-structurescoroutinesandroid-components
  • 68

    На Galaxy A34 с лимитом heap 256 МБ после 24 открытий и закрытий сканера документов на CameraX heap растёт с 67 до 196 МБ, а PSS со 119 до 258 МБ; OOM начинается примерно на 228 МБ heap. LeakCanary удерживает 24 ScannerActivity через задачу анализатора ImageAnalysis в очереди отдельного executor, лямбда которой захватывает Activity и preview binding. Что вы изменили и чем ограничили регрессию?

    data-structureslambdaandroid-components
  • 69

    На Nokia G50 с лимитом heap 256 МБ после 18 открытий фотопросмотрщика и возвратов heap вырос с 72 до 213 МБ, а PSS со 130 до 274 МБ; OOM появлялся примерно на 232 МБ heap. LeakCanary нашёл 18 удерживаемых View PhotoFragment через самописный кеш изображений. Как вы это исправили?

    cachingdata-structures
  • 70

    На Pixel 5 с лимитом heap 256 МБ после 45 циклов LoginActivity -> HomeActivity -> выход heap вырос с 55 до 174 МБ, а PSS со 106 до 238 МБ; OOM происходил примерно на 221 МБ heap. LeakCanary нашёл 45 удерживаемых LoginActivity через auth listener. Как вы исправили владение и поставили защиту от регрессии?

    ownershipdata-structures
  • 71

    После ровно 12 открытий и закрытий ProfileFragment heap растёт с 58 до 137 МБ, а PSS со 111 до 206 МБ. LeakCanary показывает ровно 12 удерживаемых ProfileFragment, каждый из которых удерживается observer репозитория, зарегистрированным через LiveData.observeForever и захватывающим binding фрагмента. Остановите ли вы раскатку на 20% и какие доказательства, исправление и релизный порог потребуете?

    android-componentsarchitecture-componentsdata-structures
  • 72

    Устройство с 512 МБ памяти падает после просмотра 18 товаров: heap растёт с 96 до 318 МБ, PSS достигает 466 МБ, а HPROF-дамп показывает 13 удерживаемых bitmap 2048x2048 ARGB_8888 общим объёмом около 208 МиБ в ProductImageRepository.previewCache. Будете ли вы настраивать кеш, менять загрузку изображений или откатывать релиз?

    cachingdata-structuresrollback
  • 73

    Через 6 часов после раскатки версии 8.3.0 на 25% доля сессий без падений снижается с 99,72% до 98,91%; Crashlytics связывает 61% новых падений с OutOfMemoryError в BitmapFactory.nativeDecodeStream, причём 78% происходят на Android 8-9 с объёмом RAM менее 2 ГБ. Продолжите, остановите или откатите раскатку и как докажете исправление?

    sessionsrollback
  • 74

    Версия 5.9.1 на 40% снижает долю пользователей без падений с 99,88% до 99,31%; верхний стек содержит NullPointerException в CheckoutMapper.kt:87 при null в response.payment.methods, а Play Console показывает, что 92% случаев произошли на API 34 после попадания в backend-эксперимент B. Выпустите патч, отключите эксперимент или продолжите раскатку?

    experimentsapifundamentals
  • 75

    При раскатке на 15% доля сессий без падений снижается с 99,81% до 99,22%, а 1840 событий имеют общий IllegalStateException: Can not perform this action after onSaveInstanceState в FragmentManager.checkStateLoss, вызванный доставкой результата из OfferViewModel через 300-900 мс после ухода в фон. Используете allowingStateLoss, отложите транзакцию или остановите релиз?

    transactionssessionsandroid-components
  • 76

    После раскатки нативных видеофильтров на 30% доля пользователей без падений снижается с 99,76% до 98,84%; Play Console сообщает о 3260 падениях SIGSEGV по адресу pc 0x18f4 в libfilters.so, 81% на arm64 Android 14, но загруженные символы относятся к версии 2.6.0, а в production находится 2.6.1. Откатите ли вы релиз до символикации и что должен доказать нативный патч?

    rollback
  • 77

    Версия 11.2.0 достигает 50%, и доля сессий без падений меняется с 99,90% до 99,43%; Crashlytics объединяет 2410 обфусцированных NullPointerException в a.a.b(:17), 74% возникают только в minified release, а mapping-файл R8 не загружен. Остановите ли вы раскатку и как отличите проблему оптимизатора от ошибки приложения?

    sessionsoptimization
  • 78

    Патч мессенджера на 10% снижает исходный IllegalStateException с 0,42% до 0,01%, но общая доля сессий без падений остаётся 99,34% против baseline 99,82%; теперь Crashlytics показывает 690 событий IndexOutOfBoundsException в MessageListAdapter.onBindViewHolder:214, 96% после reconnect для списков из 200 и более элементов. Продвинете, удержите или откатите патч?

    indexessessions
  • 79

    После версии 7.4.0 ночной расход батареи за 8 часов растёт с 3,8% до 12,6%; Battery Historian показывает, что SyncService удерживает PARTIAL_WAKE_LOCK 5 часов 47 минут за 143 захвата, а Perfetto показывает повтор worker каждые 2 минуты без сети. Остановите раскатку или только измените constraints WorkManager?

    resiliencejetpack
  • 80

    Релиз на 20% увеличивает фоновый расход с 0,55% до 1,48% в час; Perfetto фиксирует 312 пробуждений радиомодуля и 186 HTTPS-запросов за 60 минут в фоне против прежних 18 и 6, причём 84% создают три независимо запланированных analytics worker. Отключите выгрузку аналитики, объедините её в пакеты или продолжите раскатку?

    batchhttps
  • 81

    После релиза 9.1 восьмичасовой тест вне смены с выключенным экраном расходует 16,8% заряда вместо 3,2% и фиксирует 936 пробуждений в час. Battery Historian показывает 6 часов 51 минуту сканирования Bluetooth LE, а Perfetto и диагностика Bluetooth показывают, что scanner продолжает получать 74 callback в минуту после закрытия экрана смены. Как вы поведёте инцидент, не превращая его в исправление планирования синхронизации?

    jobsandroid-componentsincidents
  • 82

    Сбойный релиз API вызывает потерю 27% заряда за шесть часов, 2180 пробуждений в час и 1,8 ГБ трафика на устройство. Perfetto показывает пересекающиеся повторы OkHttp, а Battery Historian показывает, что WorkManager перезапускает ту же цепочку загрузки. Какое исправление вы одобрите?

    deploymentnetworkingapi
  • 83

    Сборка для курьеров теряет 22% заряда за четырёхчасовую смену, вызывает 940 пробуждений в час и отправляет 760 МБ. Battery Historian связывает основную часть расхода с GPS, а Perfetto показывает callback геолокации каждые 10 секунд с последующим polling, даже когда курьер неподвижен. Как вы измените это, не сломав отслеживание?

    callbacks
  • 84

    После окончания воспроизведения foreground service продолжает работать всю ночь; затронутые телефоны теряют 31% заряда, показывают 1 680 пробуждений в час и передают 2,4 ГБ за десять часов. Perfetto показывает polling прогресса каждые пять секунд, а Battery Historian показывает, что процесс сервиса никогда не переходит в простой. Каков ваш план для продакшена?

    android-componentsconcurrency
  • 85

    После 20 поворотов экрана профиля продакшен-диагностика показывает 146 активных coroutine jobs, 12 дублирующихся коллекторов пользователя и 24 одинаковых запроса в минуту; LeakCanary удерживает четыре уничтоженных экземпляра ProfileActivity, а DebugProbes указывает на запуски GlobalScope в Activity. Что вы измените и чем ограничите приемку?

    android-componentscoroutines
  • 86

    После пяти выходов из оформления заказа и повторных открытий появляются 63 активных jobs, шесть дублирующихся коллекторов цены и 30 запросов котировки в минуту. LeakCanary показывает два очищенных CheckoutViewModel, удерживаемых callback репозитория, а дамп DebugProbes показывает jobs, запущенные во внедренном application scope. Как вы исправите владение?

    ownershipcallbacks
  • 87

    После десяти минут прокрутки ленты остаются 312 активных jobs, 48 дублирующихся коллекторов элементов и 192 запроса метаданных изображений в минуту. DebugProbes ведёт jobs к RecyclerView holder, а LeakCanary удерживает три уничтоженных FeedFragment через адаптер. Что вы одобрите?

    ui
  • 88

    После семи открытий и закрытий карты остаются 91 активный job, семь дублирующихся коллекторов геолокации и 84 запроса обратного геокодирования в минуту. LeakCanary удерживает три уничтоженных MapActivity, а DebugProbes и трасса корутин останавливаются внутри callbackFlow без кадра очистки. Как вы решите проблему?

    callbackscoroutines
  • 89

    После 300 рекомпозиций экрана уведомлений Compose диагностика показывает 124 активных coroutine jobs, 41 дублирующийся коллектор настроек и 205 запросов настроек в минуту. LeakCanary удерживает три очищенных NotificationViewModel, а стеки создания DebugProbes ведут к SideEffect, который при каждом выполнении запускает коллектор во внедрённом application scope. Почему изменение ключа LaunchedEffect не объясняет утечку и что вы исправите и проверите?

    composecoroutinesandroid-components
  • 90

    После пяти отмен экспорта и выходов с экрана остаются 204 активных jobs, 32 дублирующихся запроса загрузки и четыре удерживаемых уничтоженных ExportActivity. DebugProbes показывает дочерние загрузки, продолжающиеся после отмены, LeakCanary ведёт через listener прогресса, а трассы показывают, что CancellationException обрабатывается как ошибка для повтора. Как вы закроете инцидент?

    resilienceincidents
  • 91

    Ежедневное обновление аккаунта завершалось с опозданием до девяти часов на 18% устройств после перехода приложения в Doze или App Standby. Продакт просит гарантию в 30 минут. Как вы исследуете и переработаете решение?

  • 92

    Фоновые сессии геолокации прекращаются через 40-70 минут на части устройств Xiaomi и Samsung, а на Pixel продолжаются. В отчётах о сбоях ничего нет. Что вы сделаете?

    sessions
  • 93

    Шторм переподключений поставил в очередь 14 копий одной синхронизации, израсходовал 11% батареи и создал конфликтующие записи. Как вы исправите схему WorkManager?

    designjetpack
  • 94

    Пользователь нажимает «Отправить», но expedited-запрос WorkManager после исчерпания квоты иногда запускается через 12 минут. Команда сейчас обещает доставку за 10 секунд. Что вы измените?

    jetpackpromises
  • 95

    После перехода на target Android 14 длительный экспорт, запущенный из фона, выбрасывает исключения foreground service, а у части успешных запусков нет видимого уведомления. Как вы это исправите и проверите?

    android-componentserror-handling
  • 96

    Загрузка видео размером 1,5 ГБ начинается с нуля после каждого завершения процесса, и в нестабильной мобильной сети завершается только 62% загрузок. Продакт просит гарантировать завершение за ночь. Спроектируйте восстановление и сформулируйте честную гарантию.

    designconcurrency
  • 97

    Junior-разработчик добавил три утечки Activity в двух релизах, сохраняя view и callback в singleton. Как вы его обучите и докажете улучшение?

    android-componentscallbacks
  • 98

    Junior перехватил `Exception` в шести местах с coroutine и проглотил `CancellationException`, из-за чего два экрана продолжали работу после ухода с них. Как вы его обучите?

    error-handlingcoroutinesmentoring
  • 99

    Junior изучает трассировку Perfetto, снятую на устройстве с экраном 60 Гц, и решает, что кадр длительностью 240 мс вызван layout в RecyclerView, хотя трасса показывает ожидания binder и декодирование изображений. Как вы устраните пробел в навыке?

    uitracing
  • 100

    Junior выпустил 18 instrumentation-тестов с 14% сбоев в CI, в основном из-за sleep, общего состояния и селекторов, привязанных к переведённому тексту. Как вы научите его сделать набор стабильным?

    testing