Android — Вопросы на собеседовании

Вопросы по Android Core (Activity, Services, Broadcasts), архитектурным компонентам Jetpack, Kotlin Coroutines и Dependency Injection.

Каковы основные компоненты Android приложения (Android App Components)?

Android-приложение строится на основе четырех базовых компонентов: 1. **Activity (Активность)**: Элемент интерфейса, представляющий один экран приложения, с которым взаимодействует пользователь. 2. **Service (Служба)**: Компонент для выполнения фоновых задач без предоставления пользовательского интерфейса (например, проигрывание музыки, загрузка файлов). 3. **Broadcast Receiver (Приемник широковещательных сообщений)**: Компонент для прослушивания и реагирования на глобальные системные события или сообщения от других приложений (например, изменение статуса зарядки батареи, включение режима полета). 4. **Content Provider (Поставщик содержимого)**: Компонент для управления доступом к структурированным данным приложения (например, адресной книге) и обмена ими с другими приложениями.

Каков жизненный цикл Activity в Android?

Жизненный цикл Activity управляется операционной системой с помощью колбэков: * `onCreate()`: Вызывается при первом создании Activity. Здесь происходит инициализация данных и макет экрана. * `onStart()`: Activity становится видимой для пользователя. * `onResume()`: Activity выходит на передний план и начинает принимать ввод пользователя. Запуск анимаций и обновлений датчиков. * `onPause()`: Activity частично теряет фокус (например, перекрыта диалоговым окном). Здесь нужно приостанавливать анимации. * `onStop()`: Activity больше не видна пользователю. * `onDestroy()`: Вызывается перед полным уничтожением Activity (при закрытии экрана или нехватке памяти у ОС). * `onRestart()`: Вызывается, если Activity возвращается из остановленного состояния (`onStop`) обратно на передний план.

В чем разница между Service, IntentService и Bound Service?

* **`Service`**: Базовый сервис. Выполняет операции в **главном потоке** (Main Thread) приложения по умолчанию. Требует ручного создания фонового потока, чтобы не заблокировать интерфейс. * **`IntentService`**: Наследник Service. Выполняет задачи последовательно в **отдельном рабочем потоке**. Автоматически завершает свою работу после выполнения всех задач. (Помечен как Deprecated в современных API в пользу WorkManager). * **`Bound Service`**: Служба, к которой могут привязаться другие компоненты приложения (например, Activity) с помощью `bindService()`. Позволяет обмениваться данными через IPC (Inter-Process Communication).

В чем разница между Serializable и Parcelable в Android?

Оба интерфейса используются для сериализации данных при передаче между компонентами (через `Intent` или `Bundle`): * **`Serializable`**: Стандартный Java-интерфейс. Работает на основе рефлексии рантайма. Прост в использовании (не требует написания кода), но работает очень медленно и создает много временных объектов, нагружая Garbage Collector. * **`Parcelable`**: Специфичный для Android интерфейс. Сериализация пишется разработчиком вручную (или генерируется с помощью `@Parcelize` плагина в Kotlin). Работает в разы быстрее, так как данные сериализуются напрямую в бинарный поток IPC.

Что такое Kotlin Coroutines и в чем их преимущество перед стандартными потоками?

Корутины (Coroutines) — это легковесные потоки выполнения, встроенные в язык Kotlin на уровне компилятора. * **Преимущества**: * **Легковесность**: Можно запускать сотни тысяч корутин на одном физическом потоке ОС без накладных расходов на переключение контекста процессора. * **Неблокирующий код**: Корутины используют механизм приостановки (`suspend`). Когда корутина ожидает сетевой запрос, она засыпает, освобождая нижележащий поток выполнения для других корутин. * **Структурированная конкурентность (Structured Concurrency)**: Позволяет связывать жизненный цикл запущенных корутин с жизненным циклом компонентов UI (например, через `viewModelScope`).

В чем разница между Launch и Async в Kotlin Coroutines?

Оба метода используются для запуска корутин, но имеют разное назначение: * **`launch`**: Запускает корутину по принципу «выстрелил и забыл» (fire-and-forget). Возвращает объект `Job`, с помощью которого можно отменить выполнение, но не возвращает результат работы. * **`async`**: Запускает корутину и ожидает возвращения результата. Возвращает `Deferred<T>` (аналог Promise). Для получения результата нужно вызвать приостанавливающий метод `await()` на объекте Deferred.

Что такое Dispatchers в Kotlin Coroutines и какие основные типы существуют?

Диспечеры (Dispatchers) указывают корутине, на каком именно потоке (или пуле потоков) должен выполняться код: * **`Dispatchers.Main`**: Главный UI-поток Android. Используется для обновления интерфейса и легких задач. * **`Dispatchers.IO`**: Пул потоков для операций ввода-вывода (сетевые запросы, чтение/запись БД, работа с файлами). Автоматически масштабируется. * **`Dispatchers.Default`**: Пул потоков для ресурсоемких вычислений (парсинг JSON, сортировка массивов, обработка изображений). Размер равен числу ядер процессора. * **`Dispatchers.Unconfined`**: Запускает корутину в текущем потоке до первой точки приостановки (не рекомендуется для использования в продакшене).

В чем разница между LiveData, StateFlow и SharedFlow в Android?

* **`LiveData`**: Архитектурный компонент Jetpack. Привязан к жизненному циклу Android-компонентов (Lifecycle-aware), обновляет UI только тогда, когда Activity активна. Работает исключительно в главном потоке. * **`StateFlow`**: Горячий Kotlin Flow, представляющий состояние. Всегда хранит последнее значение и требует начального состояния. Рекомендуется как замена LiveData в многоплатформенных и чистых Kotlin проектах. * **`SharedFlow`**: Горячий поток событий (hot stream). Не хранит состояние по умолчанию (но поддерживает replay). Идеален для отправки разовых событий (показ Toast, навигация, вывод SnackBar), которые не должны дублироваться при повороте экрана.

Что такое Jetpack Compose и чем он отличается от классического XML Layout?

* **XML Layout**: Императивный подход. Элементы UI объявляются в XML, а затем разработчик вручную обновляет их состояние в коде с помощью `findViewById` или ViewBinding. Сложно синхронизировать состояние. * **Jetpack Compose**: Декларативный UI фреймворк на чистом Kotlin. Интерфейс описывается функциями, помеченными `@Composable`. UI автоматически перестраивается (происходит рекомпозиция), когда изменяются связанные с ним переменные состояния (`State`). Упрощает разработку и уменьшает объем шаблонного кода.

Что такое Dependency Injection (DI) и какие фреймворки популярны в Android?

Dependency Injection (внедрение зависимостей) — это паттерн проектирования, при котором зависимости объекта передаются ему извне, а не создаются им самим. **Популярные фреймворки**: * **Dagger 2**: Мощный классический фреймворк. Проверяет зависимости на этапе компиляции, генерируя Java-код. Очень быстрый в рантайме, но сложен в настройке. * **Hilt**: Официальная библиотека от Google, построенная поверх Dagger 2 специально для Android. Упрощает инициализацию и связывает зависимости с жизненным циклом Activity/ViewModel. * **Koin / Kodein**: Легковесные сервис-локаторы на чистом Kotlin. Зависимости разрешаются в рантайме (lazy-load), просты в настройке, не требуют компиляции аннотаций.

Что такое WorkManager и когда его использовать?

`WorkManager` — это библиотека Jetpack для выполнения фоновой работы, которая должна быть гарантированно выполнена, даже если приложение закрыто или устройство перезагружено. Он автоматически выбирает оптимальный способ выполнения (JobScheduler, AlarmManager) с учетом ограничений устройства (наличие интернета, зарядка батареи).

Разница между MVP, MVVM и MVI архитектурами в Android?

* **MVP**: Presenter хранит ссылки на View и Model. Изменения передаются во View императивно через интерфейсы. View и Presenter жестко связаны 1:1. * **MVVM**: ViewModel предоставляет потоки данных (StateFlow, LiveData), на которые подписывается View. View сама реагирует на изменения данных. ViewModel ничего не знает об Activity. * **MVI (Model-View-Intent)**: Развитие MVVM с однонаправленным потоком данных (Unidirectional Data Flow). Пользователь генерирует намерения (Intent), они обрабатываются, создавая новое состояние (State), которое отправляется во View в виде единого объекта.

Как устроен Room Persistence Library под капотом?

`Room` — это ORM-надстройка над встроенной базой данных SQLite в Android. На этапе компиляции Room анализирует аннотации `@Database`, `@Dao`, `@Entity`, проверяет SQL-запросы на корректность структуры таблиц и генерирует Java-код с реализацией методов доступа к данным.

Что такое ANR (Application Not Responding) и как его избежать?

ANR — это окно предупреждения системы, возникающее, когда приложение блокирует главный UI поток более чем на 5 секунд (или Broadcast Receiver более чем на 10 секунд). Чтобы избежать ANR, все длительные задачи (сеть, БД, сложные вычисления) необходимо выполнять в фоновых потоках (корутинах с Dispatchers.IO/Default).

Разница между запуском Activity с флагами FLAG_ACTIVITY_CLEAR_TOP и FLAG_ACTIVITY_SINGLE_TOP?

* **`FLAG_ACTIVITY_SINGLE_TOP`**: Если запускаемая Activity уже находится на вершине стека (Back Stack), то новая не создается, а вызывается метод `onNewIntent()` у существующей. * **`FLAG_ACTIVITY_CLEAR_TOP`**: Если запускаемая Activity уже есть в стеке, все Activity, находящиеся выше нее, уничтожаются, и она выходит на вершину. По умолчанию она пересоздается, если не скомбинирована с `FLAG_ACTIVITY_SINGLE_TOP`.

Что такое View Binding и Data Binding в Android?

* **View Binding**: Замена `findViewById`. Генерирует класс привязки для каждого XML-макета, обеспечивая безопасный доступ к view по ID без риска NullPointerException. * **Data Binding**: Более мощный инструмент, позволяющий связывать переменные данных из кода напрямую с элементами UI в XML-макете, используя специальный синтаксис внутри XML.

В чем разница между Cold и Hot Flow в Kotlin?

* **Cold Flow (холодный поток)**: Ленивый поток. Код внутри флоу не начинает выполняться, пока у потока не появится подписчик (вызов метода `collect`). У каждого подписчика свой собственный запуск потока. * **Hot Flow (горячий поток)**: Активный поток. Выполняет код независимо от наличия активных подписчиков. Рассылает значения всем подписчикам одновременно (как броадкаст). Пример: `SharedFlow`, `StateFlow`.

Что такое Navigation Component в Android Jetpack?

Navigation Component — это библиотека для управления переходами между экранами приложения (обычно фрагментами). Он использует единый XML-граф навигации (`nav_graph`), автоматизирует анимации переходов, передачу аргументов (Safe Args) и интеграцию с боковым меню или нижней панелью навигации.

Что такое Lifecycle-aware components?

Это компоненты, которые умеют следить за изменением состояния жизненного цикла других компонентов (например, Activity или Fragment) и автоматически выполнять действия при наступлении определенных событий (например, отписываться от данных в `onStop()`). Реализуется через интерфейсы `LifecycleObserver`.

Каково назначение класса Application в Android?

Класс `Application` является базовым классом для поддержки глобального состояния всего приложения. Его экземпляр создается самым первым при запуске процесса приложения и уничтожается последним. Используется для глобальной инициализации библиотек (например, Firebase, DI контейнеров, логирования).

Что такое память JVM Heap и Stack в контексте Android?

* **Stack (Стек)**: Память для выполнения потоков. Хранит локальные переменные примитивных типов и ссылки на объекты. Аллокация происходит мгновенно. * **Heap (Куча)**: Память для хранения самих объектов. Общая для всего приложения. Работа с кучей медленнее, очисткой кучи занимается сборщик мусора (GC).

В чем отличие между val и var в Kotlin?

* **`val`**: Переменная только для чтения (read-only). Ей можно присвоить значение только один раз (аналог `final` в Java). * **`var`**: Мутабельная переменная, значение которой можно изменять многократно в ходе работы программы.

Что такое lateinit var и lazy делегат в Kotlin?

* **`lateinit var`**: Отложенная инициализация переменной. Используется только с `var` ненулевого типа. Разработчик гарантирует компилятору, что инициализирует переменную до первого обращения к ней. * **`by lazy`**: Ленивая инициализация свойства константы `val`. Значение вычисляется ровно один раз при первом обращении к свойству и кэшируется. По умолчанию потокобезопасно.

Что такое CoroutineScope и CoroutineContext?

* **`CoroutineScope`**: Определяет жизненный цикл и границы запущенных внутри него корутин. Содержит в себе `CoroutineContext`. * **`CoroutineContext`**: Набор элементов, конфигурирующих работу корутины. Основные элементы: `Job` (управление жизненным циклом), `CoroutineDispatcher` (выбор потока), `CoroutineName` (имя для отладки), `CoroutineExceptionHandler` (перехват ошибок).

Что такое сопрограммы (Cooperative multitasking) в корутинах?

Кооперативная многозадачность означает, что корутины должны явно уступать процессорное время друг другу в точках приостановки (например, `yield()` или `delay()`). Если запустить корутину с бесконечным блокирующим циклом без suspend вызовов, отменить ее обычными методами не удастся.

Как работают Channels в Kotlin Coroutines?

`Channel` — это потокобезопасный способ передачи потока данных между корутинами (паттерн Очередь / Трубопровод). Одна корутина отправляет данные через метод `send()`, другая принимает через `receive()`. Бывают буферизованные и небуферизованные каналы.

В чем разница между константами const val и val?

* **`const val`**: Константа времени компиляции (compile-time). Объявляется только на верхнем уровне файла или внутри `companion object`. Ее значение вшивается в код компилятором. * **`val`**: Константа времени выполнения (run-time). Может вычисляться динамически в ходе работы программы.

Что такое расширения (Extension Functions) в Kotlin?

Расширения позволяют добавлять новые методы в существующие классы (даже системные, код которых нельзя изменить) без необходимости наследоваться от них. Объявляются как обычные функции с префиксом целевого класса (например, `fun String.myMethod()`). Под капотом транслируются в статические методы.

Что такое Companion Object в Kotlin?

`companion object` — это объект, объявляемый внутри класса, методы и свойства которого можно вызывать напрямую по имени класса (аналог статических членов класса `static` в Java, но являющийся полноценным объектом в рантайме).

Как устроен механизм инфлейтинга макетов (LayoutInflater) в Android?

`LayoutInflater` считывает XML-файл разметки интерфейса, парсит его структуру тегов и динамически конструирует Java/Kotlin объекты классов View (например, `LinearLayout`, `TextView`), выстраивая их в древовидную иерархию элементов на экране.

Как устроен жизненный цикл Activity и разница между onStart() и onResume()?

Жизненный цикл Activity управляется операционной системой: * `onCreate()`: Первоначальное создание. Разметка UI, привязка данных. * `onStart()`: Activity становится видимой пользователю на экране. * `onResume()`: Activity выходит на передний план, начинает принимать пользовательский ввод. * `onPause()`: Теряет фокус (например, перекрыто полупрозрачным диалогом), ввод заблокирован. * `onStop()`: Полностью скрывается из вида. * `onDestroy()`: Выгрузка из памяти. **Разница между onStart() и onResume()**: В `onStart` Activity видна, но с ней еще нельзя взаимодействовать (она не в фокусе). В `onResume` Activity находится на переднем плане и полностью интерактивна.

Как устроен механизм запуска процессов в Android (Zygote)?

В Android для экономии времени запуска приложений и памяти используется специальный родительский процесс — **Zygote**. При старте ОС процесс Zygote запускается, загружает в память все базовые классы Android SDK и системные ресурсы. Когда пользователь запускает приложение, система не создает процесс с нуля, а выполняет системный вызов `fork()` от Zygote. Новый процесс мгновенно получает копию предзагруженных ресурсов. Благодаря оптимизации Copy-on-Write операционной системы, общие ресурсы физически не копируются, а делятся между процессами в памяти.

В чем разница между Service, IntentService и WorkManager?

* **`Service`**: Компонент для фоновых задач. По умолчанию выполняется в **главном (UI) потоке** приложения. Для долгих операций нужно вручную создавать фоновый поток. * **`IntentService`**: Наследник Service. Автоматически создает рабочий поток для обработки входящих намерений (Intents) по очереди и останавливается сам после завершения работы. Помечен как Deprecated. * **`WorkManager`**: Современная библиотека Jetpack для гарантированного выполнения фоновых задач, даже если приложение закрыто или устройство перезагружено. Учитывает условия (наличие интернета, зарядки) и автоматически выбирает оптимальный планировщик (JobScheduler, AlarmManager).

Как избежать утечек памяти при работе с Fragment и ViewBinding?

Fragment живет дольше, чем его иерархия View (так как фрагмент может сохраняться в бэкстеке при уничтожении View). Если сохранить ссылку на ViewBinding в поле фрагмента и не занулить ее, возникнет утечка памяти. **Правильный паттерн**: ```kotlin class MyFragment : Fragment() { private var _binding: MyFragmentBinding? = null private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { _binding = MyFragmentBinding.inflate(inflater, container, false) return binding.root } override fun onDestroyView() { super.onDestroyView() _binding = null // Предотвращаем утечку памяти! } } ```

Что такое Looper, Handler и MessageQueue в Android?

Это механизмы обработки сообщений и переключения задач между потоками: * **`MessageQueue`**: Очередь, содержащая сообщения (`Message`) и блоки кода (`Runnable`), которые нужно выполнить. * **`Looper`**: Бесконечный цикл, привязанный к потоку. Он постоянно опрашивает `MessageQueue` на наличие новых задач и передает их на исполнение. * **`Handler`**: Инструмент для отправки задач в `MessageQueue` ассоциированного потока и их обработки. Используется для выполнения фонового кода и передачи результатов обратно в главный (UI) поток (через `Handler(Looper.getMainLooper())`).

Разница между @State в Compose и LiveData / StateFlow?

* **LiveData / StateFlow**: Архитектурные хранилища данных. Они являются платформенно-независимыми (StateFlow — часть Kotlin Coroutines) и используются на уровне ViewModel для хранения бизнес-состояния. * **`MutableState` (`@State` / `remember`)**: Специальный тип состояния в Jetpack Compose. Он напрямую интегрирован с рантаймом отрисовки Compose. При изменении значения MutableState рантайм автоматически запускает рекомпозицию (перерисовку) тех Composable-функций, которые читали это состояние.

Как работает механизм рекомпозиции в Jetpack Compose?

Рекомпозиция — это процесс повторного вызова Composable-функций при изменении данных. * **Интеллектуальная перерисовка**: Compose не перерисовывает весь экран. Он строит дерево рендеринга и точечно обновляет только те функции, чьи аргументы или читаемые `@State` переменные изменились. * **`remember`**: Сохраняет объект в памяти во время рекомпозиции, предотвращая его сброс. * **`derivedStateOf`**: Используется для оптимизации. Генерирует состояние, зависящее от других состояний, но запускает рекомпозицию только тогда, когда результат вычисления реально меняется (например, при скролле списка выше определенного элемента).

Что такое стабильные типы (Stability) в Jetpack Compose?

Compose делит типы данных на стабильные (Stable) и нестабильные: * **Stable (стабильные)**: Иммутабельные типы (String, примитивы) или классы, которые уведомляют Compose об изменениях. Если аргументы Composable-функции стабильны и не изменились, Compose пропускает (skips) вызов этой функции при рекомпозиции. * **Unstable (нестабильные)**: Мутабельные типы (например, стандартные коллекции `List`, `Map` из Java/Kotlin). Compose не может гарантировать их неизменность, поэтому Composable-функции с нестабильными аргументами перерисовываются при каждой рекомпозиции. Для исправления используют Kotlinx Immutable Collections или аннотацию `@Stable`.

Что такое Side Effects в Jetpack Compose и какие основные функции есть?

Composable-функции должны быть чистыми (без побочных эффектов). Side Effect — это любое действие, выходящее за рамки отрисовки UI (запрос в сеть, подписка на датчики). Основные функции управления эффектами: * **`LaunchedEffect`**: Запускает корутину при появлении Composable на экране. Перезапускается, если меняются переданные ключи. * **`DisposableEffect`**: Используется для эффектов, требующих очистки (например, подписка на BroadcastReceiver). Содержит блок `onDispose` для отмены подписки. * **`SideEffect`**: Выполняется при каждой успешной рекомпозиции для синхронизации состояния Compose с внешними объектами.

Как устроен Dagger 2 под капотом и отличие от Hilt?

* **Dagger 2**: Фреймворк Dependency Injection, работающий на этапе компиляции (Compile-time). С помощью процессора аннотаций (APT/KSP) Dagger анализирует граф зависимостей и генерирует чистый Java-код (фабрики, провайдеры) для ручного связывания объектов. Не использует медленную рефлексию в рантайме. * **Hilt**: Библиотека-обертка над Dagger 2, созданная Google. Hilt упрощает интеграцию DI в Android, автоматически создавая стандартные контейнеры (Components) для классов Android (Application, Activity, Fragment, ViewModel) и управляя их жизненным циклом, избавляя от написания шаблонного кода (boilerplate).

В чем разница между Dependency Injection (Dagger/Hilt) и Service Locator (Koin)?

* **Dependency Injection (Dagger/Hilt)**: Зависимости передаются классу извне. Граф зависимостей проверяется и генерируется на этапе компиляции. Ошибки отсутствия зависимостей выявляются при сборке проекта. Минус — долгая сборка (build time). * **Service Locator (Koin)**: Класс сам запрашивает зависимости у глобального локатора (`by inject()`). Все связи разрешаются динамически во время выполнения приложения (Runtime). Ошибки отсутствия зависимостей упадут в рантайме (crash), но Koin работает быстрее при компиляции и проще в настройке.

Как работают Kotlin Coroutines под капотом?

Корутины — это легковесные потоки, построенные на концепции **подвешивания (suspension)**. Компилятор преобразует функции с ключевым словом `suspend` в конечный автомат с помощью передачи колбэка (`Continuation`). * При вызове приостанавливающей операции корутина сохраняет текущее состояние (локальные переменные) в объект `Continuation` и освобождает поток ОС для других задач. * Поток не блокируется. Когда асинхронная операция завершается, рантайм вызывает метод `resume()`, возвращая сохраненное состояние корутины в поток выполнения.

В чем разница между launch и async в корутинах?

* **`launch`**: Запускает корутину по принципу «выстрелил и забыл» (fire-and-forget). Возвращает объект `Job`, с помощью которого можно управлять жизненным циклом корутины (отменить). Исключения внутри `launch` сразу пробрасываются в обработчик ошибок потока. * **`async`**: Запускает корутину, которая должна вернуть результат. Возвращает `Deferred<T>` (наследник `Job`). Чтобы получить результат, нужно вызвать метод `await()`. Если внутри корутины произошла ошибка, она упадет только в момент вызова `await()`.

Что такое Structured Concurrency в Kotlin Coroutines?

Structured Concurrency (структурированная конкурентность) гарантирует, что время жизни дочерних корутин привязано к времени жизни их родительской области видимости (`CoroutineScope`). * Если родительская корутина отменяется, все ее дочерние корутины автоматически отменяются. * Родителю нельзя завершить выполнение, пока не завершатся все его дочерние процессы. * Ошибка в дочерней корутине автоматически распространяется вверх по дереву, отменяя родительский Scope (если не используется `SupervisorJob`).

Разница между Flow, StateFlow и SharedFlow?

* **`Flow`**: Холодный поток данных (Cold Stream). Код внутри Flow начинает выполняться только тогда, когда вызывается терминальный метод сбора (`collect`). Не хранит историю данных. * **`SharedFlow`**: Горячий поток (Hot Stream). Активен независимо от наличия подписчиков. Может транслировать события нескольким коллекторам одновременно. Настраивается буфер истории (`replay`). * **`StateFlow`**: Специализированный `SharedFlow` с историей в 1 элемент. Всегда хранит текущее состояние (свойство `.value`), требует начального значения и присылает обновления подписчикам только при изменении состояния (distinctUntilChanged).

Как устроен Android Keystore System?

Android Keystore System используется для безопасного хранения криптографических ключей шифрования. Ключи хранятся в защищенной системной области памяти (Hardware-backed keystore), недоступной для приложений и ядра ОС (например, TEE — Trusted Execution Environment или Secure Element). Приложение может использовать ключ для шифрования, дешифрования или подписи данных, отправляя данные в Keystore API, но сам приватный ключ никогда не покидает защищенный аппаратный модуль, что исключает его кражу вредоносным ПО.

В чем разница между Serializable и Parcelable?

* **`Serializable`**: Стандартный интерфейс Java. Использует рефлексию для сериализации объектов, что создает множество временных объектов и нагружает GC. Работает медленно. * **`Parcelable`**: Специфичный для Android интерфейс. Сериализация пишется вручную (или генерируется с помощью `@Parcelize`), где все поля объекта записываются в бинарный поток данных `Parcel` напрямую. Работает значительно быстрее и тратит меньше памяти.

Разница между ViewBinding и DataBinding в Android?

* **`ViewBinding`**: Простая библиотека для замены `findViewById`. Генерирует класс привязки для каждого XML-макета, предоставляя типы для всех View с ID. Не влияет на скорость сборки и не поддерживает логику внутри XML. * **`DataBinding`**: Более мощный инструмент. Позволяет связывать данные ViewModel напрямую с View в XML-файле разметки с помощью выражений `@{...}`. Требует больше ресурсов процессора на кодогенерацию во время сборки приложения.

Опишите Clean Architecture в контексте Android.

Clean Architecture делит код приложения на независимые слои, где зависимости направлены строго снаружи внутрь: 1. **Data Layer (Внешний)**: Источники данных (API, База данных, SharedPreferences). Содержит реализации репозиториев. 2. **Domain Layer (Центральный)**: Чистая бизнес-логика. Содержит интерфейсы репозиториев, сущности (Entities) и сценарии использования (Use Cases). Не зависит от библиотек Android и UI. 3. **Presentation Layer (Внешний)**: Пользовательский интерфейс (UI Compose/Views, ViewModel). Отвечает за отображение данных на экране.

Как оптимизировать размер APK приложения?

Способы оптимизации размера сборки: * Использовать формат **Android App Bundle (AAB)** вместо APK для сборки под конкретное устройство в Google Play. * Включить сжатие кода и ресурсов R8/Proguard (`minifyEnabled true`, `shrinkResources true`). * Перевести растровые изображения в векторный формат VectorDrawable или использовать формат WebP. * Удалить неиспользуемые локализации ресурсов с помощью `resConfigs`. * Использовать динамическую загрузку тяжелых библиотек или ассетов (Dynamic Delivery).

Назад ко всем разделам · Посмотреть тарифы Hinterly