Подготовка к собеседованию — Android-разработчик
Колода из 161+ карточек с вопросами для собеседования по направлению «Android-разработчик» — по темам и уровню сложности, с повторениями по вашим оценкам. Посмотрите несколько карточек ниже, затем выберите доступ, чтобы учить всё направление по расписанию в стиле Anki (SM-2).
Новым подписчикам месяца или года может быть доступно 7 дней бесплатно. Условия и сумму подтвердит страница оплаты.
С чего начать
Нужны основы Kotlin и опыт создания небольшого Android-приложения. В общих алгоритмах есть примеры на Python; потренируйтесь переносить эти идеи в Kotlin.
Первый проход: Kotlin и система типов → Корутины и Flow. Начните с базовых вопросов в этих модулях, затем продолжайте по плану. К сложным и senior-вопросам возвращайтесь по требованиям вакансии; все карточки доступны с самого начала.
Общие темы могут входить в несколько направлений и сохраняют одну историю повторений. План ниже отмечает общие основы и профильные модули; выбирайте глубину под свою вакансию.
Что внутри
Все темы направления, сгруппированные так, как вы будете их учить.
Kotlin и система типов
11 карточекПрофильный модуль
Корутины и Flow
12 карточекПрофильный модуль
Компоненты и жизненный цикл
10 карточекПрофильный модуль
UI: Views и Jetpack Compose
11 карточекПрофильный модуль
Архитектура Android-приложений
10 карточекПрофильный модуль
Сеть и хранение данных
10 карточекПрофильный модуль
Производительность и внутреннее устройство
10 карточекПрофильный модуль
Тестирование и инструменты
9 карточекПрофильный модуль
Основы CS
43 карточкиОбщие основы
Поведенческое интервью
35 карточекОбщие основы
Примеры вопросов
Несколько карточек из колоды — откройте ответ, затем выберите доступ, чтобы учить весь набор по расписанию.
Чем val отличается от var и делает ли val объект неизменяемым?
Чем val отличается от var и делает ли val объект неизменяемым?
Короткий ответ: var позволяет повторное присваивание, val — нет. Ни один вариант не делает объект неизменяемым. List<T> — интерфейс только для чтения: другая ссылка всё ещё может изменить базовую коллекцию.
val backing = mutableListOf(1, 2)
val view: List<Int> = backing
backing.add(3)
println(view) // [1, 2, 3]: read-only не значит immutable
val snapshot = backing.toList()
backing.add(4)
println(snapshot) // [1, 2, 3]
Подробно:
valс хранимым значением сохраняет ссылку. Свойство с кастомным getter может возвращать другое значение при каждом обращении:val now: Long get() = System.currentTimeMillis().toList()создаёт отдельную поверхностную копию: структурные изменения исходной коллекции на неё не влияют, но изменяемые объекты-элементы остаются общими. Глубокая неизменяемость требует также неизменяемых элементов и контроля владения.const val— константа времени компиляции на верхнем уровне или внутриobject/companion object, с допустимым примитивным значением или String.
Важно: val вместе с List запрещает повторное присваивание и запись через этот интерфейс, но не гарантирует неизменяемость всего графа объектов.
Источники: Коллекции Kotlin, копирование коллекций.
Что такое корутина и чем suspend отличается от блокировки потока?
Что такое корутина и чем suspend отличается от блокировки потока?
Короткий ответ: Корутина — легковесная единица конкурентности поверх потоков. Приостановка (suspend) «паркует» корутину и освобождает поток под другую работу; блокировка держит поток занятым. Поэтому тысячи корутин спокойно живут на одном потоке.
Подробно:
// Блокировка: поток занят и бесполезен
fun blocking() {
Thread.sleep(1000) // поток спит — недоступен никому
}
// Приостановка: корутина паркуется, поток свободен
suspend fun suspending() {
delay(1000) // поток в это время выполняет другие корутины
}
fun main() = runBlocking {
repeat(100_000) { launch { delay(1000) } } // ок даже на одном потоке
// 100 000 потоков с Thread.sleep(1000) — OutOfMemoryError
}
- Приостановка ≠ блокировка —
delayвозвращает управление диспатчеру,Thread.sleepудерживает поток. - Лёгкость — корутина это объект в куче (continuation + стейт), а не стек ~1 МБ, как у потока.
- Кооперативность — корутина уступает поток только в точках приостановки (suspension points).
⚠️ Частая ошибка: «саспенд-функция выполняется в фоновом потоке». Нет: suspend сам по себе поток не переключает — где выполняться, решает диспатчер.
Назови полный жизненный цикл Activity — какие колбэки и зачем нужен каждый?
Назови полный жизненный цикл Activity — какие колбэки и зачем нужен каждый?
Короткий ответ: Три «поднимающих» колбэка — onCreate → onStart → onResume — выводят экран к пользователю; три «опускающих» — onPause → onStop → onDestroy — убирают. onRestart вызывается, когда остановленная Activity снова возвращается на экран.
Подробно:
onCreate() ← создан: setContentView, init, чтение savedInstanceState
│
onStart() ← стал видимым
│
onResume() ← на переднем плане, принимает ввод
│
[ RESUMED — работает ]
│
onPause() ← потерял фокус (частично перекрыт)
│
onStop() ← полностью не виден ──onRestart()→onStart() при возврате
│
onDestroy() ← уничтожен (finish или нехватка памяти)
- onCreate — единственный обязательный; здесь инфляция layout, инициализация, восстановление из
savedInstanceState. - onStart / onStop — граница видимости: регистрируем и снимаем то, что нужно только видимому экрану.
- onResume / onPause — граница фокуса и ввода; onPause обязан быть коротким — следующий экран не покажется, пока он не вернётся.
- onDestroy — финал; может не прийти при убийстве процесса, поэтому критичное сохраняем раньше.
⚠️ Частая ошибка: считать onDestroy гарантированным местом для сохранения. При process death его не будет — сохраняйте в onSaveInstanceState / onStop.
Что такое рекомпозиция и что её запускает?
Что такое рекомпозиция и что её запускает?
Короткий ответ: Рекомпозиция — повторный вызов @Composable-функций, когда меняется прочитанное ими состояние. Запускает её запись в наблюдаемый State (mutableStateOf, StateFlow через collectAsState и т.п.), который был прочитан внутри composable. Перевызываются только те функции, что читали именно это значение.
Подробно:
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Text("Clicks: $count") // читает count → перевызовется
Button(onClick = { count++ }) { // запись в count → рекомпозиция
Text("Tap") // count не читает → пропустится
}
}
- Триггер — не «любое изменение», а запись в snapshot-состояние, которое читалось в конкретной composable. Compose отслеживает чтения и инвалидирует ровно нужные scope'ы.
- Оптимистична — если во время рекомпозиции состояние снова поменялось, текущий проход отбрасывается и стартует заново.
- Неупорядочена и может идти параллельно — порядок выполнения соседних composable не гарантирован; нельзя закладываться на side-effect'ы прямо в теле.
⚠️ Частая ошибка: обычная var без mutableStateOf — это не state; её изменение Compose не видит и рекомпозицию не запустит, UI «застынет».
Что такое MVVM и почему ViewModel не должна ссылаться на View или Context?
Что такое MVVM и почему ViewModel не должна ссылаться на View или Context?
Короткий ответ: MVVM делит экран на три роли: Model (данные и логика), View (Activity/Fragment/Composable — только рисует и передаёт действия) и ViewModel (держит состояние и переживает пересоздание View). ViewModel не знает про конкретную View — она лишь публикует состояние, на которое View подписывается.
Подробно:
┌────────┐ подписка на state ┌───────────┐ запрос данных ┌───────┐
│ View │ ◄─────────────────── │ ViewModel │ ──────────────► │ Model │
│ (тупая)│ ── действия (события) ─►│ (state) │ ◄─── данные ──── │(repo) │
└────────┘ └───────────┘ └───────┘
- View — тупой рендер — берёт готовое состояние и рисует; никакой бизнес-логики, только «показать то, что дали».
- ViewModel — держатель состояния — переживает поворот экрана (её создаёт
ViewModelStoreOwner, а не пересоздаёт вместе с Activity). - Model — репозитории, БД, сеть; ViewModel обращается к ним, а не View напрямую.
⚠️ Частая ошибка: хранить View, Activity или Context в поле ViewModel. ViewModel живёт дольше View — после поворота ссылка указывает на уничтоженную Activity, и это утечка памяти. Нужен Context — берите AndroidViewModel.getApplication() или инжектите @ApplicationContext.
Из чего состоит стек Retrofit + OkHttp и за что отвечает каждый слой?
Из чего состоит стек Retrofit + OkHttp и за что отвечает каждый слой?
Короткий ответ: Retrofit — верхний, декларативный слой: превращает Kotlin-интерфейс с аннотациями в HTTP-запросы и парсит ответ через Converter. OkHttp под ним — сам HTTP-клиент: сокеты, пул соединений, кэш, интерцепторы, таймауты, повторы. Retrofit без OkHttp не работает — это его транспорт.
Подробно:
┌─────────────────────────────────────────┐
│ ApiService (interface + @GET/@POST) │ ← ваш код
├─────────────────────────────────────────┤
│ Retrofit: аннотации → Request, │
│ Converter (JSON ↔ data class) │
├─────────────────────────────────────────┤
│ OkHttp: interceptors, connection pool, │
│ cache, timeouts, TLS, retry │
├─────────────────────────────────────────┤
│ Socket / сеть │
└─────────────────────────────────────────┘
- Retrofit — знает про
suspendи возвращает готовый data class; сам JSON не парсит. - Converter — kotlinx.serialization / Moshi / Gson; именно он делает JSON ↔ объект.
- OkHttp — вся сетевая механика; один
OkHttpClientна приложение, чтобы пул и кэш переиспользовались. - CallAdapter — поддержка
suspend-функций из коробки.
⚠️ Частая ошибка: создавать новый OkHttpClient/Retrofit на каждый запрос. Тогда теряются пул соединений и кэш; клиент должен быть синглтоном на всё приложение.
Готовы лучше запоминать?
Посмотрите пример, выберите направление и настройте регулярную практику под свою подготовку.
Вопросы об этом направлении
Как готовиться к собеседованию на «Android-разработчик»?
Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «Android-разработчик» в RecallDeck даёт 161+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2), основанному на ваших оценках — чтобы тренировать вспоминание и объяснение. Дополняйте повторения кодингом и пробными собеседованиями.
Какие темы охватывает направление «Android-разработчик»?
Направление «Android-разработчик» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.
Помогает ли интервальное повторение в подготовке к «Android-разработчик»?
Да. Активное вспоминание и честная самооценка помогают закреплять знания. RecallDeck назначает повторения карт по направлению «Android-разработчик» на основе ваших оценок: знакомые карты возвращаются реже, а сложные получают больше практики.
Можно попробовать направление «Android-разработчик» до оплаты?
Новым подписчикам месячного или годового тарифа может быть доступен пробный период семь дней со всем направлением «Android-разработчик» и всеми функциями. Право на него и сумму подтвердит страница оплаты; при повторной подписке списание может быть сразу. Отмените подписку онлайн до конца пробного периода, чтобы избежать первого списания. У вечного доступа пробного периода нет.