RecallDeck
Направление

Подготовка к собеседованию — Android-разработчик

Колода из 161+ карточек с вопросами для собеседования по направлению «Android-разработчик» — по темам и уровню сложности, с возвратом ровно перед тем, как вы забудете. Посмотрите несколько карточек ниже, затем войдите, чтобы учить всё направление по расписанию в стиле Anki (SM-2).

161 карточка10 тем

Бесплатно · вход через GitHub · ваш прогресс остаётся с вами.

Что внутри

Все темы направления, сгруппированные так, как вы будете их учить.

Kotlin и система типов

11 карточек
Kotlin и типы

Корутины и Flow

12 карточек
Корутины и Flow

Компоненты и жизненный цикл

10 карточек
Компоненты и жизненный цикл

UI: Views и Jetpack Compose

11 карточек
Views и Compose

Архитектура Android-приложений

10 карточек
Архитектура

Сеть и хранение данных

10 карточек
Сеть и хранение

Производительность и внутреннее устройство

10 карточек
Производительность

Тестирование и инструменты

9 карточек
Тестирование и инструменты

Основы CS

43 карточки
Структуры данных и алгоритмы

Поведенческое интервью

35 карточек
Поведенческое интервью

Примеры вопросов

Несколько карточек из колоды — откройте ответ, затем войдите, чтобы учить весь набор по расписанию.

Чем val отличается от var и делает ли val объект неизменяемым?

Короткий ответ: var — перезаписываемая ссылка, val — read-only: присвоить повторно нельзя. Но val замораживает только ссылку, а не содержимое объекта: val list = mutableListOf<Int>() спокойно принимает list.add(1). Настоящая неизменяемость — это read-only тип плюс val.

Подробно:

val a = mutableListOf(1, 2)
a.add(3)          // ✅ ссылка та же, содержимое меняется
// a = mutableListOf() // ❌ val нельзя переприсвоить

var n = 0
n = 1             // ✅ var переприсваивается

val now: Long get() = System.currentTimeMillis() // val с getter — не константа!
const val API = "v1"  // const — время компиляции, только примитивы и String
  1. val ≠ immutable — гарантирует лишь стабильность ссылки; изменяемость зависит от типа (List vs MutableList).
  2. val с кастомным getter — вычисляется при каждом обращении, значение может меняться от вызова к вызову.
  3. const val — подставляется компилятором в место использования; допустим только на top-level или в object/companion, значение — примитив или String.

⚠️ Частая ошибка: считать val синонимом «immutable». val про ссылку, а не про глубину объекта.

Что такое корутина и чем 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
}
  1. Приостановка ≠ блокировкаdelay возвращает управление диспатчеру, Thread.sleep удерживает поток.
  2. Лёгкость — корутина это объект в куче (continuation + стейт), а не стек ~1 МБ, как у потока.
  3. Кооперативность — корутина уступает поток только в точках приостановки (suspension points).

⚠️ Частая ошибка: «саспенд-функция выполняется в фоновом потоке». Нет: suspend сам по себе поток не переключает — где выполняться, решает диспатчер.

Назови полный жизненный цикл Activity — какие колбэки и зачем нужен каждый?

Короткий ответ: Три «поднимающих» колбэка — onCreate → onStart → onResume — выводят экран к пользователю; три «опускающих» — onPause → onStop → onDestroy — убирают. onRestart вызывается, когда остановленная Activity снова возвращается на экран.

Подробно:

     onCreate()    ← создан: setContentView, init, чтение savedInstanceState

     onStart()     ← стал видимым

     onResume()    ← на переднем плане, принимает ввод

   [ RESUMED — работает ]

     onPause()     ← потерял фокус (частично перекрыт)

     onStop()      ← полностью не виден  ──onRestart()→onStart() при возврате

     onDestroy()   ← уничтожен (finish или нехватка памяти)
  1. onCreate — единственный обязательный; здесь инфляция layout, инициализация, восстановление из savedInstanceState.
  2. onStart / onStop — граница видимости: регистрируем и снимаем то, что нужно только видимому экрану.
  3. onResume / onPause — граница фокуса и ввода; onPause обязан быть коротким — следующий экран не покажется, пока он не вернётся.
  4. 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 не читает → пропустится
    }
}
  1. Триггер — не «любое изменение», а запись в snapshot-состояние, которое читалось в конкретной composable. Compose отслеживает чтения и инвалидирует ровно нужные scope'ы.
  2. Оптимистична — если во время рекомпозиции состояние снова поменялось, текущий проход отбрасывается и стартует заново.
  3. Неупорядочена и может идти параллельно — порядок выполнения соседних composable не гарантирован; нельзя закладываться на side-effect'ы прямо в теле.

⚠️ Частая ошибка: обычная var без mutableStateOf — это не state; её изменение Compose не видит и рекомпозицию не запустит, UI «застынет».

Что такое MVVM и почему ViewModel не должна ссылаться на View или Context?

Короткий ответ: MVVM делит экран на три роли: Model (данные и логика), View (Activity/Fragment/Composable — только рисует и передаёт действия) и ViewModel (держит состояние и переживает пересоздание View). ViewModel не знает про конкретную View — она лишь публикует состояние, на которое View подписывается.

Подробно:

┌────────┐  подписка на state   ┌───────────┐  запрос данных  ┌───────┐
│  View  │ ◄─────────────────── │ ViewModel │ ──────────────► │ Model │
│ (тупая)│ ── действия (события) ─►│ (state)   │ ◄─── данные ──── │(repo) │
└────────┘                       └───────────┘                 └───────┘
  1. View — тупой рендер — берёт готовое состояние и рисует; никакой бизнес-логики, только «показать то, что дали».
  2. ViewModel — держатель состояния — переживает поворот экрана (её создаёт ViewModelStoreOwner, а не пересоздаёт вместе с Activity).
  3. Model — репозитории, БД, сеть; ViewModel обращается к ним, а не View напрямую.

⚠️ Частая ошибка: хранить View, Activity или Context в поле ViewModel. ViewModel живёт дольше View — после поворота ссылка указывает на уничтоженную Activity, и это утечка памяти. Нужен Context — берите AndroidViewModel.getApplication() или инжектите @ApplicationContext.

Из чего состоит стек 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 / сеть                            │
└─────────────────────────────────────────┘
  1. Retrofit — знает про suspend и возвращает готовый data class; сам JSON не парсит.
  2. Converter — kotlinx.serialization / Moshi / Gson; именно он делает JSON ↔ объект.
  3. OkHttp — вся сетевая механика; один OkHttpClient на приложение, чтобы пул и кэш переиспользовались.
  4. CallAdapter — поддержка suspend-функций из коробки.

⚠️ Частая ошибка: создавать новый OkHttpClient/Retrofit на каждый запрос. Тогда теряются пул соединений и кэш; клиент должен быть синглтоном на всё приложение.

Готовы закрепить навсегда?

Первая сессия — меньше минуты. Ваше будущее «я» на собеседовании скажет спасибо.

Вопросы об этом направлении

Как готовиться к собеседованию на «Android-разработчик»?

Учите концепции, которые придётся объяснять, а не только те, что умеете кодить. Направление «Android-разработчик» в RecallDeck даёт 161+ отобранных вопросов и возвращает каждый по расписанию в стиле Anki (SM-2) ровно перед тем, как вы забудете — чтобы на собеседовании ответы были под рукой.

Какие темы охватывает направление «Android-разработчик»?

Направление «Android-разработчик» разбито на ключевые области, которые реально проверяют на таких собеседованиях, — по темам и уровню сложности (Concept, Junior, Middle, Senior). Полный план и примеры вопросов можно посмотреть выше до входа.

Помогает ли интервальное повторение в подготовке к «Android-разработчик»?

Да. Активно вспоминать ответ и честно себя оценивать — куда прочнее для памяти, чем перечитывать заметки. RecallDeck планирует каждую карту «Android-разработчик» так, чтобы она вернулась перед моментом забывания: ежедневных повторений становится меньше, а знания держатся.

Направление «Android-разработчик» бесплатное?

Да — направление «Android-разработчик» и полный планировщик SM-2 бесплатны, с 20 новыми картами в день. Войдите через GitHub, и прогресс синхронизируется с аккаунтом. RecallDeck Pro ($5/мес или $29/год) поднимает дневной лимит и добавляет блиц-режим.

Другие направления

RecallDeckПодготовка к собеседованию на интервальных повторениях