PrepBro
Профессии
PrepBro
Профессия:

Подготовка

  • Вопросы3339
  • Задачи12

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Профессия:

Подготовка

  • Вопросы3339
  • Задачи12

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Все 24 профессии
Android DeveloperData AnalystSystem Analyst1С DeveloperiOS DeveloperBusiness AnalystJava DeveloperData ScientistQA EngineerQA AutomationPHP BackendC/C++ BackendDevOps EngineerIT Project ManagerFrontend DeveloperNode.js BackendUnity DeveloperC# BackendProduct AnalystFlutter DeveloperPython DeveloperIT Product ManagerGo DeveloperData Engineer

© 2026 PrepBro. Все права защищены.

Telegram-бот

Вопросы по Android Developer

Как объявлять разрешения в манифесте?
1.0 Junior🔥 30💬 3

Объявление разрешений в AndroidManifest.xml

Работа с разрешениями в Android — фундаментальный аспект разработки, требующий строгого соблюдения правил безопасности и конфиденциальности пользователей. Разрешения объявляются в файле AndroidManifest.xml, который является главным конфигурационным файлом приложения.

Основные типы разрешений

Android делит разрешения на несколько категорий:

Читать полностью ->
Что такое Intent в Android? В чём разница между explicit и implicit Intent?
1.0 Junior🔥 30💬 1

Что такое Intent в Android?

Intent (намерение) — это фундаментальный механизм в Android, представляющий собой объект-сообщение, который используется для запроса выполнения действия от другого компонента приложения или от другого приложения. По сути, это абстракция, описывающая операцию, которую необходимо выполнить. Основные цели Intent:

  • Активация компонентов (Activity, Service, BroadcastReceiver)
  • Передача данных между компонентами
  • Декларативное описание действий, что позволяет системе находить подходящий компонент для их выполнения
Читать полностью ->
Что такое парадигма Publisher/Subscriber?
2.0 Middle🔥 30💬 1

Что такое парадигма Publisher/Subscriber (Pub/Sub)?

Парадигма Publisher/Subscriber (издатель/подписчик) — это архитектурный шаблон обмена сообщениями, основанный на асинхронной событийно-ориентированной коммуникации между компонентами системы. Она полностью декапсулирует отправителя (publisher) и получателя (subscriber), связывая их через абстрактный канал или шину событий (event bus), часто называемую посредником (broker) или диспетчером. В отличие от прямого вызова методов или паттерна Observer, где наблюдатель знает об наблюдаемом объекте, здесь издатель и подписчик не знают о существовании друг друга.

Ключевые компоненты и принцип работы

Читать полностью ->
Что такое лямбда-выражение?
1.6 Junior🔥 30💬 2

Что такое лямбда-выражение в Kotlin/Java для Android?

Лямбда-выражение — это анонимная функция, которая не объявляется явно, а используется "по месту" как литерал. В контексте Android-разработки на Kotlin (реже на Java) лямбды являются фундаментальной частью функционального программирования, значительно упрощая код, особенно при работе с коллекциями, асинхронными операциями и слушателями событий UI.

Ключевые характеристики лямбда-выражений

  1. Анонимность — у лямбды нет имени, но её можно присвоить переменной.
  2. Краткость — синтаксис лаконичнее анонимных классов (в Java) или обычных функций.
  3. Замыкания — лямбда может захватывать и использовать переменные из окружающего контекста.
  4. Совместимость с функциональными интерфейсами — лямбда автоматически преобразуется в объект интерфейса с одним абстрактным методом (SAM-интерфейс).

Синтаксис в Kotlin (основной для Android)

Общий вид: { параметры -> тело }

Читать полностью ->
Что знаешь про жизненный цикл Application
1.0 Junior🔥 30💬 1

Жизненный цикл класса Application в Android

Класс Application в Android является базовым классом для глобального состояния приложения. Это singleton, который создается системой при старте процесса вашего приложения и существует до его завершения. Его жизненный цикл напрямую связан с жизненным циклом самого процесса приложения и является более высокоуровневым, чем жизненный цикл Activity или Fragment.

Ключевые методы жизненного цикла Application

Основные методы, которые переопределяются для управления глобальным состоянием:

Читать полностью ->
Можно ли сделать так, чтобы метод onStop у Activity не вызывался?
1.0 Junior🔥 30💬 1

Можно ли предотвратить вызов onStop() в Activity?

Нет, это невозможно гарантированно предотвратить. Метод onStop() является частью жизненного цикла Activity, который строго управляется системой Android (в частности, ActivityManager и WindowManager). Он вызывается системой в ответ на определенные события, и разработчик не может напрямую запретить его вызов без вмешательства в работу фреймворка, что недопустимо в обычной разработке.

Почему onStop() вызывается системой?

onStop() вызывается, когда Activity больше не видна пользователю. Это происходит в нескольких ключевых сценариях:

  1. Полное перекрытие другим Activity: Когда новое Activity занимает весь экран.
  2. Сворачивание приложения: Пользователь нажал кнопку "Home" или переключился на другое приложение.
  3. Изменение конфигурации: Например, поворот экрана (если не предотвращено), что приводит к уничтожению и повторному созданию Activity.
Читать полностью ->
Что переопределить у класса для его хранения в HashMap в качестве ключа
1.0 Junior🔥 30💬 1

Методы для использования класса как ключа в HashMap

Чтобы использовать собственный класс в качестве ключа в HashMap, необходимо гарантировать корректную работу двух фундаментальных операций: определения уникальности ключа и поиска соответствующего элемента в структуре данных. Для этого требуется переопределить два критически важных метода в классе: equals() и hashCode().

Почему это необходимо?

HashMap использует хеш-таблицу для организации данных. При добавлении или поиске элемента:

  1. Сначала вычисляется hashCode() ключа для определения "ведра" (bucket).
  2. Если в одном "ведре" находятся несколько ключей (коллизия), используется equals() для точного сравнения.

Если эти методы не переопределены корректно, работа HashMap нарушится:

  • Возможны дублирование ключей.
  • Поиск может не найти существующий элемент.
  • Возникнут проблемы с удалением элементов.

Переопределение equals()

Читать полностью ->
Какие знаешь способы передачи данных между двумя экранами?
1.0 Junior🔥 30💬 2

Основные подходы к передаче данных между экранами в Android

В разработке Android приложений передача данных между Activity, Fragment или другими компонентами является фундаментальной задачей. Ниже представлены наиболее распространенные и эффективные методы, которые я использую в своей практике, учитывая современные архитектурные подходы и лучшие практики.

1. Использование Intent для передачи между Activity

Это классический способ, предусмотренный самой системой Android. Intent служит как для запуска активности, так и для передачи данных через его extras.

// Отправка данных из первой Activity
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("USER_NAME", "Алексей")
intent.putExtra("USER_ID", 42)
startActivity(intent)

// Получение данных в SecondActivity
val userName = intent.getStringExtra("USER_NAME")
val userId = intent.getIntExtra("USER_ID", 0)
Читать полностью ->
Какие знаешь основные подходы для построения архитектуры приложения?
1.8 Middle🔥 30💬 1

Основные архитектурные подходы для Android-приложений

В Android-разработке выбор архитектуры — это фундаментальное решение, определяющее масштабируемость, тестируемость и поддерживаемость кода. Вот ключевые подходы, которые я применяю на практике.

1. Многослойная архитектура (Layered Architecture)

Это классический подход, разделяющий код на слои с чёткими ответственностями.

  • Слой представления (Presentation Layer): Активности, Фрагменты, ViewModel. Отвечает за UI и взаимодействие с пользователем.
  • Слой бизнес-логики (Domain Layer): Use Case-ы или Interactor-ы. Инкапсулирует ключевые правила приложения.
  • Слой данных (Data Layer): Репозитории, источники данных (локальная БД, сетевые API). Управляет получением и хранением данных.
Читать полностью ->
Какие знаешь операторы для обработки пустых значений?
1.0 Junior🔥 30💬 1

Обработка пустых значений в Kotlin для Android-разработки

В Kotlin существует богатый набор операторов для безопасной работы с nullable-типами, что является одной из ключевых особенностей языка. Вот основные операторы, которые я использую в Android-разработке:

Безопасные операторы

?. (safe call operator) - самый распространённый оператор для безопасного вызова методов или свойств

val length: Int? = text?.length // вернёт null если text == null

?: (elvis operator) - позволяет предоставить значение по умолчанию

val displayName: String = user?.name ?: "Гость"
val listSize: Int = list?.size ?: 0

Проверки и приведение типов

!! (not-null assertion) - явное утверждение, что значение не null (может вызвать NullPointerException)

val definitelyNotNull: String = nullableString!! // Опасно!

as? (safe cast operator) - безопасное приведение типа с возвратом null при неудаче

Читать полностью ->
Какие знаешь map функции?
1.0 Junior🔥 30💬 2

Map функции в Kotlin для коллекций

Map функции в Kotlin — это семейство операций высшего порядка для трансформации элементов коллекции, возвращающих новую коллекцию с преобразованными данными. Я выделю ключевые из них, объясню различия и приведу примеры.

Основные map функции

  1. map — базовая трансформация каждого элемента
val numbers = listOf(1, 2, 3)
val squared = numbers.map { it * it } // [1, 4, 9]
  1. mapIndexed — трансформация с доступом к индексу
val letters = listOf("a", "b", "c")
val indexed = letters.mapIndexed { index, value -> 
    "$index: $value" 
} // ["0: a", "1: b", "2: c"]
  1. mapNotNull и mapIndexedNotNull — фильтрация null-результатов
val mixed = listOf("1", "2", "a", "3")
val numbersOnly = mixed.mapNotNull { it.toIntOrNull() } // [1, 2, 3]

Специализированные варианты для разных коллекций

Читать полностью ->
Какие данные можно сложить в Intent
1.2 Junior🔥 30💬 1

Что можно передать через Intent

В Android Intent — это объект, представляющий намерение (intention) выполнить действие, такое как запуск Activity, Service или передачу широковещательного сообщения (Broadcast). Он используется как контейнер для передачи данных между компонентами приложения (или даже между разными приложениями). Данные в Intent хранятся в виде пар ключ-значение, где ключ — это строка, а значение может быть одного из допустимых типов.

Основные типы данных для передачи через Intent

Intent поддерживает передачу так называемых "extra data" через методы putExtra(). Вот основные типы, которые можно использовать:

1. Примитивные типы и их обёртки

  • int, boolean, char, byte, short, long, float, double
  • Соответствующие классы-обёртки: Integer, Boolean и т.д.
intent.putExtra("score", 100);
intent.putExtra("isPremium", true);
Читать полностью ->
Как написать цикл в Kotlin
1.0 Junior🔥 30💬 1

Отличный вопрос! Kotlin предлагает несколько способов написания циклов, каждый из которых предназначен для различных сценариев. Как опытный разработчик, я всегда выбираю цикл, наиболее точно соответствующий задаче и согласующийся с философией Kotlin — безопасность, выразительность и функциональный подход.

Основные типы циклов в Kotlin:

1. Цикл for

Это самый распространённый цикл для перебора коллекций или диапазонов.

Перебор диапазона (Range)

// От 1 до 5 включительно
for (i in 1..5) {
    println(i) // Выведет: 1, 2, 3, 4, 5
}

// От 1 до 4 (до 5 исключительно)
for (i in 1 until 5) {
    println(i) // Выведет: 1, 2, 3, 4
}

// С шагом
for (i in 1..10 step 2) {
    println(i) // Выведет: 1, 3, 5, 7, 9
}

// В обратном порядке
for (i in 5 downTo 1) {
    println(i) // Выведет: 5, µ4, 3, 2, 1
}

Перебор коллекций (массивов, списков, множеств)

val list = listOf("A", "B", "C")

// Перебор элементов
for (item in list) {
    println(item)
}
Читать полностью ->
Как компилятор Kotlin преобразует suspend-функции
1.0 Junior🔥 30💬 3

Компиляция suspend-функций в Kotlin: механизм Continuation Passing Style

Компилятор Kotlin преобразует suspend-функции в обычный JVM-байткод, используя механизм Continuation Passing Style (CPS). Это ключевая трансформация, позволяющая реализовать корутины без изменения JVM.

Базовый принцип трансформации

При компиляции каждая suspend-функция модифицируется следующим образом:

  1. Добавляется параметр Continuation: Компилятор добавляет скрытый параметр типа Continuation<T> к каждой suspend-функции, где T - тип возвращаемого значения.
  2. Изменяется возвращаемый тип: Фактический возвращаемый тип становится Any? или Object, чтобы вмещать как реальный результат, так и специальные маркерные значения.
  3. Генерируется конечный автомат: Тело функции превращается в конечный автомат (state machine), где каждое состояние соответствует точке приостановки.

Пример трансформации

Рассмотрим простую suspend-функцию:

Читать полностью ->
Как RecyclerView будет отображать список из 100 элементов
1.0 Junior🔥 30💬 1

Как RecyclerView отображает список из 100 элементов

RecyclerView оптимизирует отображение больших списков, используя механизм переиспользования ViewHolder и ленивую загрузку. Это принципиально отличается от старого ListView и позволяет эффективно работать с сотнями и тысячами элементов без потребления чрезмерных ресурсов памяти.

Основные принципы работы

  1. ViewHolder Pattern - каждый элемент списка представлен объектом ViewHolder, который хранит ссылки на View элемента. Это позволяет избежать многократных вызовов findViewById().
  2. Recycling (Переиспользование) - когда элемент исчезает с экрана (при прокрутке), его View не уничтожается, а помещается в Recycler Pool (пул переиспользования) для последующего использования.
  3. LayoutManager - отвечает за измерение и расположение элементов (линейный, сеточный, ступенчатый макет).
  4. Адаптер (Adapter) - связывает данные с ViewHolder, создавая и привязывая элементы по мере необходимости.
Читать полностью ->
Используешь ли Coroutines
1.0 Junior🔥 30💬 1

Да, я активно использую Coroutines в разработке под Android

Coroutines — это одна из фундаментальных технологий в современной Android-разработке, и я использую их повсеместно для упрощения асинхронного программирования. Заменяя колбэки и RxJava в большинстве сценариев, корутины предлагают более читаемый, лаконичный и безопасный с точки зрения утечек памяти способ работы с фоновыми задачами, сетью, базой данных и другими операциями с задержкой.

Ключевые преимущества, почему я выбираю Coroutines

Читать полностью ->
Что такое интерфейс Converter?
1.3 Junior🔥 30💬 1

Что такое интерфейс Converter в контексте Android/Java?

Converter (Конвертер) — это функциональный интерфейс, часто используемый в различных библиотеках и фреймворках, включая Android-разработку, для преобразования объектов одного типа в объекты другого типа. Его основная цель — предоставить стандартизированный, гибкий и типобезопасный способ выполнения преобразований данных, что является частой задачей при работе с архитектурными компонентами, сетевыми слоями, базами данных или маппингом между разными моделями представления данных.

Ключевые характеристики и определение

В наиболее классическом виде (например, в библиотеке Guava от Google или в некоторых реактивных подходах) интерфейс Converter объявляется примерно так:

public abstract class Converter<A, B> implements Function<A, B> {
    // Преобразует объект типа A в тип B.
    protected abstract B doForward(A a);
Читать полностью ->
Где будешь писать работу с сетевыми запросами?
2.0 Middle🔥 30💬 1

Архитектурный подход к работе с сетевыми запросами

Работа с сетевыми запросами в современных Android приложениях требует тщательного планирования и выбора правильного архитектурного слоя. Как эксперт с 10+ лет опыта, я не рекомендую размещать сетевую логику непосредственно в Activity, Fragment или даже ViewModel. Вместо этого следует использовать принципы чистой архитектуры и разделения ответственности.

Выбор слоя: Repository и UseCase

Основное место для сетевых операций — это Repository (репозиторий) в слое данных. Этот паттерн из Domain-Driven Design прекрасно адаптируется под задачи Android.

Читать полностью ->
В чем разница между HashSet и TreeSet?
1.0 Junior🔥 30💬 2

Основные различия между HashSet и TreeSet в Java

HashSet и TreeSet — оба являются реализациями интерфейса Set в Java, что гарантирует уникальность элементов в коллекции. Однако их внутреннее устройство, производительность и поведение существенно отличаются.

1. Внутренняя структура данных

HashSet основан на хеш-таблице (реализация HashMap), где элементы хранятся с использованием механизма хеширования. Это обеспечивает константное время выполнения основных операций.

// HashSet использует HashMap внутри
public class HashSet<E> {
    private transient HashMap<E,Object> map;
    // ...
}

TreeSet основан на красно-черном дереве (реализация TreeMap), которое является самобалансирующимся бинарным деревом поиска. Элементы хранятся в отсортированном порядке.

Читать полностью ->
Что такое View Binding?
1.0 Junior🔥 30💬 2

Что такое View Binding?

View Binding (привязка представлений) – это функция Android Jetpack, которая позволяет более удобно и безопасно взаимодействовать с элементами пользовательского интерфейса (View), объявленными в XML-файлах макетов.

В отличие от традиционного метода findViewById(), View Binding автоматически генерирует класс привязки для каждого XML-файла макета. Этот класс содержит прямые ссылки на все View с указанными атрибутами android:id, что полностью исключает риск ClassCastException из-за неверного приведения типов и повышает безопасность типа (type safety) во время компиляции.

Ключевые преимущества View Binding

Читать полностью ->
Как запустить асинхронные операции в Java
1.8 Middle🔥 30💬 4

Запуск асинхронных операций в Java

В Java для запуска асинхронных операций существует несколько подходов, которые эволюционировали с развитием языка и платформы. Основная идея — выполнение задач без блокировки основного потока, что особенно критично для Android-приложений, где главный поток отвечает за отрисовку UI.

Основные механизмы асинхронности

1. Потоки (Threads)

Базовый низкоуровневый подход. Создание и управление потоками через класс Thread или реализацию интерфейса Runnable.

// Создание потока через Runnable
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // Асинхронная операция
        System.out.println("Выполняюсь в фоновом потоке");
    }
});
thread.start();

// Или через лямбду (Java 8+)
new Thread(() -> {
    // Асинхронная операция
}).start();
Читать полностью ->
Для чего нужен Dagger?
1.0 Junior🔥 30💬 1

Dagger 2: Dependency Injection для Android

Dagger — это фреймворк для автоматической инъекции зависимостей (DI) на Android. Он позволяет управлять зависимостями между объектами, делая код более тестируемым и поддерживаемым.

Проблема без Dagger

Ручное создание зависимостей

class UserViewModel(
    private val userRepository: UserRepository,
    private val analyticsService: AnalyticsService,
    private val networkService: NetworkService,
    private val cacheService: CacheService
) : ViewModel() { }

// Когда нужна ViewModel в Activity
val apiService = ApiService()
val database = AppDatabase.getDatabase(context)
val userRepository = UserRepository(apiService, database)
val analytics = AnalyticsService()
val networkService = NetworkService()
val cache = CacheService()

val viewModel = UserViewModel(userRepository, analytics, networkService, cache)
Читать полностью ->
Что такое лямбда функция в Kotlin?
1.0 Junior🔥 29💬 1

Что такое лямбда функция в Kotlin?

Лямбда функция в Kotlin — это краткий способ объявления функции без имени (анонимной функции), который может быть передана как аргумент или сохранена в переменной. Она является фундаментальной частью поддержки функционального программирования в языке и часто используется для создания чистого, декларативного и выразительного кода.

Основные характеристики лямбда функций

  • Анонимность: Лямбда не имеет явного имени, но может быть присвоена переменной или передана напрямую.
  • Сокращенный синтаксис: Объявление значительно компактнее, чем объявление обычной функции.
  • Возможность передачи: Лямбды могут быть переданы в функции высшего порядка (higher-order functions) как аргументы.
  • Замыкания (Closures): Лямбды могут захватывать и использовать переменные из окружающего контекста (области видимости, в которой они объявлены).

Синтаксис и примеры

Читать полностью ->
Что такое Recomposition?
2.0 Middle🔥 29💬 1

Что такое Recomposition (Рекомпозиция) в Jetpack Compose?

Рекомпозиция — это фундаментальный процесс в Jetpack Compose, фреймворке для построения UI в Android. Это механизм, при котором Compose автоматически заново вызывает те @Composable-функции, данные которых изменились, чтобы перерисовать (или "пересоставить") только обновленные части пользовательского интерфейса. Вместо того чтобы вручную обновлять иерархию виджетов, как в традиционном View-системе, Compose сам интеллектуально определяет, что нуждается в перерисовке, когда меняется состояние (State).

Простыми словами, рекомпозиция — это "реактивный перерасчет UI" в ответ на изменение состояния. Если упростить аналогией: ваше приложение — это функция, которая принимает состояние (State) и возвращает UI (UI = f(State)). При изменении состояния State функция f вызывается снова, и UI пересчитывается — это и есть рекомпозиция.

Ключевые принципы и особенности

Читать полностью ->
Хочешь ли рассказать что-нибудь о себе
1.3 Junior🔥 29💬 2

О себе

Привет! Меня зовут Алексей, и я Android-разработчик с более чем 10-летним опытом работы в индустрии. Моя специализация охватывает полный цикл создания мобильных приложений — от проектирования архитектуры и написания чистого, поддерживаемого кода до публикации в магазинах приложений и их дальнейшей поддержки.

Мой профессиональный путь

Читать полностью ->
С помощью чего открывается экран в Android приложении
1.0 Junior🔥 29💬 1

Открытие экранов (Activity) в Android

В Android для открытия нового экрана (который технически представлен Activity) используется механизм Intent (Намерение). Это фундаментальная концепция, которая позволяет не только запускать Activity внутри вашего приложения, но и взаимодействовать с компонентами других приложений и самой системы.

Основной механизм: Explicit и Implicit Intents

Существует два основных типа Intent для запуска Activity:

  1. Explicit Intent (Явное намерение): Используется для запуска конкретной, известной вам Activity внутри вашего же приложения. Вы прямо указываете класс целевой Activity.
    // Kotlin пример
    val intent = Intent(this, SecondActivity::class.java)
    startActivity(intent)
    ```

```java
    // Java пример
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    startActivity(intent);
    ```
Читать полностью ->
На каком протоколе транспортного уровня работает WebSocket
1.7 Middle🔥 29💬 2

На каком протоколе транспортного уровня работает WebSocket?

WebSocket работает на TCP (Transmission Control Protocol), который является основным протоколом транспортного уровня для надежной, двусторонней передачи данных. TCP обеспечивает упорядоченную, гарантированную доставку пакетов через установление соединения, контроль потока и механизмы повторной передачи — это критически важно для работы WebSocket, который предназначен для постоянного, полноценного двустороннего обмена данными между клиентом и сервером.

Почему TCP, а не UDP?

WebSocket исключительно использует TCP из-за своих фундаментальных требований:

Читать полностью ->
Может ли вызваться onDestroy без onStop?
1.3 Junior🔥 29💬 1

Краткий ответ

Да, в определенных сценариях onDestroy() может быть вызван без предварительного вызова onStop(). Это исключительная ситуация, нарушающая стандартный жизненный цикл Activity, и происходит она при принудительном уничтожении активности системой или самим приложением.

Стандартный жизненный цикл и исключение

В нормальных условиях жизненный цикл Activity следует строгой последовательности: onCreate() → onStart() → onResume() → onPause() → onStop() → onDestroy().

Однако, документация Android прямо указывает, что в двух случаях onDestroy() может быть вызван напрямую, минуя onStop() (и иногда даже onPause()):

  1. Когда система убивает процесс приложения из-за нехватки ресурсов (памяти) до того, как она успеет вызвать onStop(). Это аварийное завершение.
  2. При вызове Activity.finish() из метода onCreate() или onStart(). В этом случае система немедленно начинает завершение активности, пропуская промежуточные состояния.
Читать полностью ->
Что такое Gradle?
1.0 Junior🔥 29💬 2

Что такое Gradle?

Gradle — это система автоматизации сборки с открытым исходным кодом, которая стала стандартом для разработки под Android, а также широко используется в экосистеме Java, Kotlin и других языков. Вместо того чтобы быть просто "сборщиком", Gradle — это мощный инструмент, который управляет всем жизненным циклом проекта: от компиляции исходного кода и обработки ресурсов до тестирования, упаковки (в APK/AAB) и публикации.

Его основная философия — декларативность и гибкость. В отличие от императивных скриптов (как в Ant) или строгой конфигурации (как в Maven), Gradle позволяет описывать что нужно сделать, а не как. Это достигается с помощью DSL (Domain-Specific Language), основанного на языках Groovy или Kotlin (Kotlin Script). Для Android-разработки преимущественно используется Kotlin DSL из-за его безопасности типов, лучшей производительности и интеграции с языком проекта.

Ключевые компоненты и концепции Gradle в Android

Читать полностью ->
Какой использовал бы Flow для работы ViewModel и Fragment?
1.7 Middle🔥 29💬 2

Использование Flow в связке ViewModel и Fragment

В современной Android-разработке с Kotlin, Flow из библиотеки Kotlin Coroutines стал стандартом для обработки асинхронных потоков данных. Для работы между ViewModel и Fragment я бы использовал StateFlow и SharedFlow в зависимости от конкретных требований.

Выбор типа Flow

StateFlow для состояния UI

StateFlow идеально подходит для передачи состояния UI от ViewModel к Fragment. Он всегда имеет текущее значение и автоматически обновляет UI при изменениях.

Читать полностью ->
Какие плюсы и минусы RecyclerView?
1.8 Middle🔥 29💬 1

Плюсы и минусы RecyclerView в Android

RecyclerView является фундаментальным компонентом Android для отображения больших наборов данных в списках, таблицах или каскадных коллекциях. Он заменял устаревший ListView и GridView, предлагая более гибкую и эффективную архитектуру. Его использование стало стандартом в разработке под Android, но, как любой инструмент, он имеет свои сильные и слабые стороны.

Основные преимущества RecyclerView

Читать полностью ->
Какие знаешь способы передачи данных из ViewModel во View в MVVM?
2.2 Middle🔥 29💬 1

Способы передачи данных из ViewModel во View в архитектуре MVVM

В паттерне MVVM для Android передачи данных из ViewModel в View (обычно Activity или Fragment) использует реактивный подход, чтобы обеспечить разделение ответственности и избежать утечек памяти. Вот основные механизмы, которые я применяю на практике:

1. LiveData

LiveData — это компонент архитектуры Android, который обеспечивает поток данных с осведомлённостью о жизненном цикле. Он идеально подходит для MVVM, так как автоматически управляет подписками и обновляет UI только когда View находится в активном состоянии.

class MyViewModel : ViewModel() {
    private val _userData = MutableLiveData<User>()
    val userData: LiveData<User> get() = _userData

fun loadUser() {
        viewModelScope.launch {
            _userData.value = repository.fetchUser()
        }
    }
}

// Во Fragment
viewModel.userData.observe(viewLifecycleOwner) { user ->
    binding.textView.text = user.name
}
Читать полностью ->
Какие знаешь реализации интерфейса Collection?
1.3 Junior🔥 29💬 1

Реализации интерфейса Collection в Java

В Java интерфейс Collection является корневым для большинства коллекций в стандартной библиотеке (Java Collections Framework - JCF). Он определяет базовые операции для работы с группами объектов. Реализации делятся на несколько категорий в зависимости от их поведения и структуры данных. Вот основные из них:

Читать полностью ->
Как решаешь асинхронные задачи
2.2 Middle🔥 29💬 1

Общий подход к асинхронности в Android

Для решения асинхронных задач в Android я использую комбинацию инструментов, выбирая наиболее подходящий под конкретный сценарий. Основные проблемы, которые решает асинхронность: неблокирование UI-потока, обработка долгих операций (сетевые запросы, работа с БД, вычисления) и безопасное управление жизненным циклом компонентов.

Современные подходы и инструменты

1. Coroutines (Корутины)

Библиотека kotlinx.coroutines стала стандартом де-факто для Kotlin. Её преимущества:

  • Структурированная конкуренция — отмена и очистка ресурсов происходят автоматически
  • Suspend-функции — упрощают чтение асинхронного кода, делая его похожим на синхронный
  • Интеграция с ViewModel, Lifecycle, Room
Читать полностью ->
Когда Activity может быть уничтожена?
2.0 Middle🔥 29💬 1

Когда Activity может быть уничтожена?

Activity — ключевой компонент Android-приложения, жизненный цикл которого напрямую зависит от политики управления памятью операционной системы и действий пользователя. Уничтожение Activity — штатная ситуация, и понимание её причин критически важно для создания стабильных приложений, способных корректно восстанавливать состояние.

Основные сценарии уничтожения Activity

1. По инициативе системы Android (системное уничтожение)

Это наиболее частый случай, когда ОС вынуждена освободить ресурсы.

Читать полностью ->
Как добавить элементы в список в Kotlin
1.2 Junior🔥 29💬 1

Добавление элементов в список в Kotlin

В Kotlin, как в современном и мощном языке для Android разработки, работа со списками (List) является фундаментальной операцией. Списки в Kotlin могут быть мутабельными (изменяемыми) или иммутабельными (неизменяемыми). Важно понимать эту разницу, так как методы добавления элементов напрямую зависят от типа списка.

Основные типы списков и способы добавления элементов

1. Работа с мутабельным списком (MutableList)

Для добавления элементов в изменяемый список используется интерфейс MutableList и его методы. Самый распространенный способ создания такого списка — использование mutableListOf().

// Создание мутабельного списка
val mutableList: MutableList<String> = mutableListOf("apple", "banana")

// Основные методы добавления элементов:

// 1. add(element) - добавление в конец списка
mutableList.add("orange") // Список теперь: ["apple", "banana", "orange"]
Читать полностью ->
В чем разница между потоками и корутинами?
2.2 Middle🔥 29💬 3

Основное различие: потоки vs корутины

Потоки (threads) — это низкоуровневые механизмы многозадачности, предоставляемые операционной системой. Каждый поток имеет собственный стек, планируется системным планировщиком и работает параллельно (или псевдопараллельно на одноядерных системах).

Корутины (coroutines) — это легковесные конструкции для асинхронного программирования, реализованные на уровне языка или библиотеки. Они не привязаны к конкретным потокам и могут приостанавливать выполнение без блокировки потока.

Ключевые отличия

1. Стоимость создания и переключения контекста

// Создание потока (дорого - ~1MB стека)
Thread {
    println("Thread running")
}.start()

// Создание корутины (дешево - несколько KB)
GlobalScope.launch {
    println("Coroutine running")
}
Читать полностью ->
В чем разница между lazy и lateinit в Kotlin?
1.0 Junior🔥 29💬 1

Разница между lazy и lateinit в Kotlin

Оба механизма — lazy и lateinit — используются для отложенной инициализации свойств в Kotlin, но они решают разные задачи и имеют различные ограничения. Основное сходство в том, что они позволяют избежать инициализации свойства в момент объявления, что полезно при работе с ресурсоёмкими операциями или зависимостями, которые становятся доступными позже.

Ключевые отличия

Критерийlateinitlazy
Тип свойстваТолько var (изменяемое)Только val (только для чтения)
Поддерживаемые типыНенулевые (non-null) типы, не примитивыВсе типы, включая nullable
ИнициализацияВручную, в любом месте кодаАвтоматически при первом обращении
ПотокобезопасностьНет (если не синхронизировать вручную)Да (по умолчанию), можно отключить
Место инициализацииОбычно в onCreate(), init блоке или др.Ленивый делегат (при первом вызове getter)
Читать полностью ->
В чем разница между class и object в Kotlin?
1.3 Junior🔥 29💬 1

Различие между class и object в Kotlin

В Kotlin концепции class и object являются фундаментальными, но служат для разных целей. Основная разница заключается в том, что class описывает тип (или шаблон), из которого можно создавать множественные экземпляры (объекты), а object — это конструкция языка для создания синглтона, то есть единственного и уникального экземпляра, который существует в единственном числе во время выполнения программы.

Ключевые отличия

1. class: шаблон для создания экземпляров

class определяет структуру данных и поведения (поля, методы). Он может иметь конструкторы, наследоваться от других классов или интерфейсов, и позволяет создавать сколько угодно объектов (экземпляров).

class User(val name: String, val age: Int) {
    fun greet() {
        println("Hello, I'm $name")
    }
}

// Создание нескольких экземпляров класса
val user1 = User("Alice", 25)
val user2 = User("Bob", 30)
Читать полностью ->
Что такое паттерн Singleton?
1.0 Junior🔥 29💬 1

Паттерн Singleton (Одиночка)

Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к этому экземпляру. Это один из самых известных и часто используемых паттернов в разработке под Android, хотя его применение требует осторожности из-за потенциальных проблем с тестированием и жизненным циклом.

Основная цель и принцип работы

Главная задача Singleton — обеспечить единственность экземпляра класса на протяжении всего жизненного цикла приложения. Это достигается за счёт:

  • Приватного конструктора, который предотвращает создание экземпляра извне класса.
  • Публичного статического метода (чаще всего getInstance()), который контролирует доступ к единственному экземпляру.
  • Приватного статического поля для хранения этого экземпляра.

Базовая реализация на Java/Kotlin

Читать полностью ->
Что такое LiveData?
2.0 Middle🔥 29💬 2

Что такое LiveData?

LiveData — это класс в архитектурных компонентах Android (Android Jetpack), который представляет собой наблюдаемый (observable) держатель данных, осознающий жизненный цикл (lifecycle-aware). Это означает, что LiveData автоматически управляет подписками (обновлениями) в зависимости от состояния жизненного цикла компонентов Android, таких как Activity или Fragment, что помогает избежать утечек памяти и сокращает boilerplate-код.

Ключевые характеристики и преимущества LiveData:

Читать полностью ->
Для чего нужен файл манифеста?
2.3 Middle🔥 28💬 3

Файл AndroidManifest.xml: архитектурный фундамент приложения

AndroidManifest.xml — это обязательный конфигурационный файл в каждом Android-приложении, выполняющий роль декларативной спецификации для операционной системы. Его можно сравнить с паспортом или техническим паспортом приложения: он предоставляет Android системе критически важные метаданные, необходимые для установки, запуска и интеграции приложения в экосистему устройства.

Ключевые цели и функции манифеста

1. Идентификация приложения

Манифест содержит базовые параметры, уникально идентифицирующие приложение в системе:

  • package name: Уникальный идентификатор приложения (например, com.example.myapp). Это его постоянное имя в системе и магазинах.
  • versionCode: Целочисленное значение для внутреннего управления версиями (используется системой для определения наличия обновлений).
  • versionName: Строковое представление версии для пользователя (например, "1.2.3").
Читать полностью ->
Что такое бинарный оператор?
1.0 Junior🔥 28💬 2

Что такое бинарный оператор?

В программировании, особенно в контексте разработки для Android (Java/Kotlin), бинарный оператор — это оператор (символ или ключевое слово), который выполняет операцию над двумя операндами (значениями или переменными). Ключевое слово "бинарный" указывает на количество операндов — два. Это фундаментальная концепция в большинстве языков программирования, включая Java и Kotlin, которые являются основными для Android.

Основные типы бинарных операторов

Бинарные операторы можно разделить на несколько категорий по их функциональности:

1. Арифметические операторы

Выполняют базовые математические операции.

val a = 10
val b = 3
val sum = a + b      // Сложение: 13
val difference = a - b // Вычитание: 7
val product = a * b   // Умножение: 30
val quotient = a / b // Деление: 3 (целочисленное)
val remainder = a % b // Остаток от деления (модуль): 1
Читать полностью ->
Что такое main поток?
1.3 Junior🔥 28💬 1

Что такое main поток (Главный поток)?

В контексте Android (и Java/Kotlin) main поток — это основной поток выполнения приложения, который создается системой при его запуске. Это один из ключевых компонентов архитектуры приложения на платформе Android.

Основная роль и обязанности главного потока

Главный поток, также известный как UI-поток, выполняет несколько критически важных функций:

Читать полностью ->
Что такое apk файл?
1.0 Junior🔥 28💬 2

Что такое APK файл?

APK (от англ. Android Package Kit, иногда Android Application Package) — это формат архивного файла, используемый операционной системой Android для распространения и установки мобильных приложений и middleware. По своей сути, APK — это пакет, содержащий все необходимые компонеты приложения для его корректной работы на устройстве.

Анатомия APK файла

APK файл является ZIP-архивом, который можно открыть и исследовать с помощью любого архиватора. Его ключевые компоненты включают:

Читать полностью ->
Что если пойти в сеть на главном потоке
1.6 Junior🔥 28💬 1

Сетевое взаимодействие на главном потоке в Android

Выполнение сетевых операций на главном потоке (Main Thread/UI Thread) — это одна из наиболее критичных ошибок в разработке под Android, приводящая к серьезным последствиям для пользовательского опыта и стабильности приложения.

Что происходит технически?

Главный поток в Android отвечает за обработку всех пользовательских взаимодействий: отрисовку UI, обработку касаний, обновление виджетов и анимации. Когда вы выполняете блокирующую операцию (как сетевой запрос) на этом потоке, возникает проблема:

// ПРИМЕР НЕПРАВИЛЬНОГО КОДА
fun loadDataFromServer() {
    // Этот код выполняется на главном потоке
    val response = URL("https://api.example.com/data")
        .openStream()  // БЛОКИРУЮЩИЙ ВЫЗОВ!
        .bufferedReader()
        .use { it.readText() }
    
    textView.text = response  // Обновление UI
}

Ключевые проблемы

Читать полностью ->
Что возвращает apply?
1.0 Junior🔥 28💬 3

Что возвращает функция apply в Kotlin?

Функция apply — это одна из scope-функций (функций-областей видимости) в Kotlin, которая возвращает сам объект (this), для которого она была вызвана, после выполнения переданного лямбда-выражения.

Основные характеристики apply:

  • Контекстный объект: внутри лямбды объект доступен через this (или может быть опущен).
  • Возвращаемое значение: всегда сам объект (ресивер), над которым вызывается apply.
  • Цель использования: удобна для инициализации или настройки объекта.

Пример кода с объяснением:

data class Person(var name: String, var age: Int = 0, var city: String = "")
Читать полностью ->
С какими технологиями знаком
1.3 Junior🔥 28💬 1

Введение

Как Android-разработчик с 10+ лет опыта, я знаком с широким спектром технологий, которые охватывают не только саму платформу Android, но и смежные области, необходимые для создания современных, надежных и масштабируемых мобильных приложений. Моя экспертиза простирается от фундаментальных основ до современных архитектурных подходов и инструментов.

Языки программирования и платформа Android

Читать полностью ->
Приведи пример проверки на null
1.0 Junior🔥 28💬 2

Примеры проверки на null в Kotlin (для Android/Kotlin-разработчика)

1. Базовые подходы с оператором безопасного вызова (?.)

Самый распространённый способ в Kotlin — использовать оператор безопасного вызова (safe call operator), который возвращает null, если объект равен null:

// Безопасный вызов метода
val user: User? = getUser()
val userName: String? = user?.name // userName будет null, если user равен null

// Цепочка безопасных вызовов
val street: String? = user?.address?.street?.uppercase()

2. Оператор Элвиса (?:) для значения по умолчанию

Оператор Элвиса (Elvis operator) позволяет указать значение по умолчанию при null:

// Значение по умолчанию
val displayName: String = user?.name ?: "Гость"

// Более сложный пример с вычислением
val orderTotal: Double = calculateTotal() ?: 0.0
Читать полностью ->
Почему нельзя использовать рекурсию в inline-функции?
1.2 Junior🔥 28💬 2

Почему рекурсия запрещена в inline-функциях Kotlin

В Kotlin использование рекурсии (вызов самой себя) внутри inline-функции запрещено и приводит к ошибке компиляции. Это ограничение связано с фундаментальными особенностями механизма inline и рекурсивных вызовов, которые создают неразрешимые противоречия при компиляции.

Основная причина: невозможность корректного разворачивания рекурсии

Inline-функции предназначены для полного разворачивания (встраивания) их тела в месте вызова во время компиляции, чтобы избежать создания объектов функций и потенциально повысить производительность. Однако рекурсия по своей природе имеет неизвестное количество повторений заранее.

// НЕКОРРЕКТНЫЙ пример - приведёт к ошибке компиляции
inline fun recursiveSum(n: Int): Int {
    if (n <= 0) return 0
    return n + recursiveSum(n - 1) // Рекурсивный вызов inline-функции
}

fun main() {
    val result = recursiveSum(5) // Ошибка: recursive inline function
}
Читать полностью ->