Фильтр публикаций


🤔 Что такое UI thread и Worker thread?

1. UI thread:
- Основной поток приложения, где выполняются все операции с пользовательским интерфейсом.
- Долгие операции здесь могут привести к замораживанию приложения.
2. Worker thread:
- Фоновые потоки для выполнения долгих задач (например, обработки данных, запросов в сеть).
- Обновление UI из фонового потока невозможно.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 В чём отличие Dalvik Virtual Machine и ART(Android Run Time)?

Dalvik Virtual Machine (DVM) и Android Runtime (ART) — это две среды выполнения для запуска Android-приложений. DVM использовалась в ранних версиях Android, в то время как ART пришла на замену DVM, начиная с Android 5.0 (Lollipop). Основное различие между ними заключается в способе выполнения кода и производительности.

🚩Основные отличия между Dalvik и ART

🟠Тип выполнения кода
Dalvik Virtual Machine (DVM): Just-In-Time (JIT) компиляция
Dalvik использует JIT-компиляцию (Just-In-Time), что означает, что код приложения компилируется в машинный код во время выполнения (runtime).
Когда приложение запускается, DVM интерпретирует байт-код (.dex-файлы), а при необходимости компилирует часть кода "на лету" для повышения производительности.
Этот подход требует дополнительных ресурсов во время работы приложения, что увеличивает задержки (лаг) при запуске и потребляет больше CPU и батареи.
ART использует AOT-компиляцию (Ahead-Of-Time), которая компилирует весь код приложения в машинный код заранее — во время установки приложения.
Это устраняет необходимость интерпретации и JIT-компиляции во время работы приложения, что снижает нагрузку на процессор и улучшает производительность.

🟠Производительность
Dalvik (DVM):
Поскольку JIT-компиляция происходит во время работы приложения, это создает дополнительную нагрузку на процессор и замедляет выполнение.
Производительность ниже из-за частой интерпретации кода.
ART:
Благодаря AOT-компиляции приложения запускаются быстрее и работают плавнее.
Потребление ресурсов (CPU, батарея) значительно ниже, поскольку интерпретация и компиляция кода уже выполнены на этапе установки.

🟠Ускорение запуска приложений
Dalvik (DVM):
Приложения запускаются медленнее, так как DVM интерпретирует код во время каждого запуска.
ART:
Приложения запускаются быстрее, так как код уже компилирован в машинный код на этапе установки.

🟠Потребление батареи
Dalvik (DVM):
Потребляет больше батареи из-за того, что JIT-компиляция выполняется постоянно во время работы приложения.
ART:
Более энергоэффективен, так как большая часть работы выполнена заранее, и процессор не нагружается так сильно.

🟠Время установки приложения
Dalvik (DVM):
Приложения устанавливаются быстрее, так как код не компилируется заранее.
ART:
Приложения устанавливаются медленнее, так как на этапе установки выполняется AOT-компиляция.
Например, установка приложения в ART может занимать больше времени, чем в DVM, из-за компиляции кода.

🟠Память
Dalvik (DVM):
DVM использует меньше памяти на устройстве, так как код компилируется только во время работы приложения, и машинный код не сохраняется.
ART:
AOT-компиляция увеличивает размер приложения, так как компилированный машинный код сохраняется на устройстве. Это требует больше места в памяти.

🟠Отладка и инструменты
Dalvik (DVM):
Ограниченные возможности отладки, так как JIT-компиляция не предоставляет доступа к заранее оптимизированному коду.
ART:
ART позволяет разработчикам использовать более продвинутые инструменты отладки (например, профилирование исполнения) и лучше анализировать производительность приложений.

🟠Совместимость
Dalvik (DVM):
Dalvik был изначально разработан для устройств с ограниченными ресурсами (медленные процессоры, малый объем оперативной памяти).
Приложения работали в основном в условиях ограниченного оборудования.
ART:
ART ориентирован на современные устройства с мощными процессорами и большим объемом памяти.
Он лучше справляется с современными требованиями приложений.

🚩Пример различий

🟠На Dalvik (DVM):
- Установка быстрая.
- При запуске приложения DVM интерпретирует и компилирует код. Это требует времени и ресурсов.
- Приложение может работать медленно из-за интерпретации кода в реальном времени.
🟠На ART:
- Установка занимает больше времени, так как код компилируется сразу.
- Запуск приложения быстрый, потому что код уже готов к исполнению.
- Приложение работает плавно, так как отсутствует необходимость компиляции во время выполнения.

Ставь 👍 и забирай 📚 Базу знаний


🤔 Как расшифровывается APK?

APK — Android Package. Это архив (аналог .zip), содержащий:
- Скомпилированный код (classes.dex)
- Ресурсы (res, assets)
- Манифест (AndroidManifest.xml)
- Подпись

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Как запустить асинхронные операции в чистом Android?

В Android существует несколько способов запуска асинхронных операций. Наиболее распространённые из них включают использование AsyncTask (хотя он уже устарел), HandlerThread, AsyncTaskLoader, ExecutorService и современные подходы с использованием Kotlin Coroutines и библиотеки WorkManager.

🟠AsyncTask (устаревший)
AsyncTask был одним из первых инструментов для выполнения асинхронных задач, однако его использование сейчас не рекомендуется из-за проблем с управлением жизненным циклом и утечками памяти.
private class MyAsyncTask extends AsyncTask {
@Override
protected String doInBackground(Void... voids) {
// Выполнение длительной операции
return "Result";
}

@Override
protected void onPostExecute(String result) {
// Обновление UI после завершения операции
}
}

// Запуск
new MyAsyncTask().execute();

🟠HandlerThread
HandlerThread — это удобный способ создания фонового потока с циклом обработки сообщений.
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());

handler.post(new Runnable() {
@Override
public void run() {
// Выполнение длительной операции
}
});

🟠ExecutorService
ExecutorService из стандартной библиотеки Java предоставляет более гибкий способ управления потоками.
ExecutorService executor = Executors.newSingleThreadExecutor();

executor.submit(new Runnable() {
@Override
public void run() {
// Выполнение длительной операции
}
});

🟠Kotlin Coroutines
Корутины в Kotlin — это современный и мощный инструмент для асинхронного программирования. Они упрощают работу с асинхронными задачами и обеспечивают безопасность работы с UI.
import kotlinx.coroutines.*

fun performAsyncTask() {
GlobalScope.launch(Dispatchers.IO) {
// Выполнение длительной операции
val result = longRunningTask()

withContext(Dispatchers.Main) {
// Обновление UI после завершения операции
}
}
}

suspend fun longRunningTask(): String {
delay(1000) // Симуляция длительной операции
return "Result"
}

🟠WorkManager
WorkManager — это библиотека для выполнения фоновых задач, которая обеспечивает выполнение задач даже после закрытия приложения или перезагрузки устройства.
public class MyWorker extends Worker {
public MyWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}

@NonNull
@Override
public Result doWork() {
// Выполнение длительной операции
return Result.success();
}
}

// Запуск Worker
WorkManager workManager = WorkManager.getInstance(context);
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(MyWorker.class).build();
workManager.enqueue(request);

🟠RxJava
RxJava — это библиотека для реактивного программирования, которая также может быть использована для выполнения асинхронных задач.
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;

Observable.fromCallable(() -> {
// Выполнение длительной операции
return "Result";
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
// Обновление UI после завершения операции
});

Ставь 👍 и забирай 📚 Базу знаний


🤔 Что такое PendingIntent?

PendingIntent — это обёртка над Intent, позволяющая другим компонентам (например, системным) выполнить Intent от имени вашего приложения, даже если оно сейчас не активно.
Используется:
- В уведомлениях (NotificationManager).
- Для запуска BroadcastReceiver или Service.
- В AlarmManager.
Он играет роль разрешения: система может отложить выполнение кода, но с уже подтверждёнными правами.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Что такое лямбды с точки зрения синтаксиса в Java и Kotlin?

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

🚩Лямбда-выражения

Были введены в Java 8 и являются частью усилий по добавлению функциональных возможностей в язык. Лямбды в Java чаще всего используются с функциональными интерфейсами, которые являются интерфейсами с одним абстрактным методом.
(parameters) -> expression

или
(parameters) -> { statements; }

🚩Лямбда-выражения

Поддерживает более гибкие и выразительные лямбды по сравнению с Java. Лямбды могут использоваться как с функциональными интерфейсами, так и в качестве части синтаксиса языка, благодаря чему Kotlin особенно удобен для функционального программирования.
{ parameters -> code body }

🚩Примеры

Лямбда без параметров
{ println("Hello, World!") }

Лямбда с одним параметром
{ a: Int -> a * a }

Лямбда с несколькими параметрами
{ a: Int, b: Int -> a + b }

Лямбда с телом, содержащим несколько выражений
{ s: String ->
println(s)
s.length
}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Как заинжектить в поле в Dagger Hilt?

Чтобы внедрить зависимость, достаточно добавить аннотацию @Inject к полю и использовать @AndroidEntryPoint на компоненте. Hilt автоматически подставит нужный объект.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Что такое TransactionTooLargeException?

TransactionTooLargeException — это исключение, которое возникает, если передаваемые данные превышают лимит 1MB в Binder.
Чаще всего ошибка появляется при передаче больших объектов через Intent, Bundle, `onSaveInstanceState().

🚩Как воспроизвести `TransactionTooLargeException`?

Передача большого Bitmap через Intent (ОШИБКА!)
val bitmap: Bitmap = getLargeBitmap() // ❌ Очень большой объект

val intent = Intent(this, ImageActivity::class.java)
intent.putExtra("image", bitmap) // ❌ Ошибка: TransactionTooLargeException

startActivity(intent)

Ошибка
android.os.TransactionTooLargeException: data parcel size 2MB is larger than 1MB

🚩Как избежать `TransactionTooLargeException`?

Использовать FileProvider и Uri вместо Bitmap
val file = File(context.cacheDir, "image.png")
file.outputStream().use {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, it)
}

val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file)
val intent = Intent(this, ImageActivity::class.java).apply {
putExtra("image_uri", uri.toString())
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(intent)

🚩Использовать `ViewModel` вместо `onSaveInstanceState()`

Ошибка: сохранение больших данных в onSaveInstanceState()
override fun onSaveInstanceState(outState: Bundle) {
outState.putSerializable("largeData", myLargeObject) // ❌ ОШИБКА!
super.onSaveInstanceState(outState)
}

Решение → Используем ViewModel, чтобы хранить данные в памяти:
class MyViewModel : ViewModel() {
var largeData: MyLargeObject? = null
}

🚩Хранить данные в `SharedPreferences` или `Room`

Если данные не нужны постоянно → используем SharedPreferences
getSharedPreferences("app_prefs", MODE_PRIVATE).edit()
.putString("last_data", jsonData)
.apply()

Если данные большие и важные → используем Room
@Dao
interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun saveData(data: MyData)
}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Какие переменные можно использовать в data class?

В data class можно использовать только свойства, объявленные в первичном конструкторе (val или var). Эти свойства автоматически участвуют в:
- equals, hashCode;
- toString;
- copy и componentN.
Остальные свойства не считаются частью "данных" класса.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Как сказать адаптеру перерисовать список, если какой-то элемент удалился?

Если удалился элемент из списка, нужно:
Удалить его из списка данных.
Сообщить Adapter, чтобы он перерисовал только изменённые элементы.

🚩Используем `notifyItemRemoved()` (лучший вариант)

Этот метод обновляет только удалённый элемент, сохраняя анимации.
fun removeItem(position: Int) {
itemList.removeAt(position) // Удаляем из списка данных
notifyItemRemoved(position) // Сообщаем адаптеру
notifyItemRangeChanged(position, itemList.size) // Обновляем индексы
}

🚩Если изменился весь список – `DiffUtil`

Если изменился несколько элементов, лучше использовать DiffUtil, чтобы обновить только нужные элементы.
class MyAdapter : ListAdapter(DIFF_CALLBACK) {

companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() {
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem == newItem
}
}
}
}

Обновляем список через submitList()
fun removeItem(item: Item) {
val newList = currentList.toMutableList()
newList.remove(item)
submitList(newList) // `DiffUtil` сам вычислит, что обновить
}

🚩Полное обновление списка (`notifyDataSetChanged()`)

Использовать только если изменился весь список!
fun removeItem(position: Int) {
itemList.removeAt(position)
notifyDataSetChanged() // Перерисовывает весь список (медленно)
}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Что такое инстанциация и инициализация?

- Инстанциация — процесс создания экземпляра (объекта) класса (например, new ClassName());
- Инициализация — установка начальных значений полей и выполнение конструктора.
Инстанциация включает в себя инициализацию.
Вот подробные пояснения к каждому из ваших вопросов

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 В чем различие Default диспатчер и IO диспатчер?

В Kotlin Coroutines есть несколько диспетчеров (Dispatchers), но Default и IO используются чаще всего.

🚩Главное различие:

Dispatchers.Default — для тяжёлых вычислений (CPU-операции).
Dispatchers.IO — для операций ввода-вывода (сеть, файлы, БД).

🟠`Dispatchers.Default` – для сложных вычислений (CPU-bound)
Этот диспетчер используется, если код загружает процессор (например, сложные вычисления).
import kotlinx.coroutines.*

fun main() = runBlocking {
launch(Dispatchers.Default) {
val result = heavyComputation()
println("Результат: $result")
}
}

suspend fun heavyComputation(): Int {
delay(1000)
return (1..1_000_000).sum()
}

🟠`Dispatchers.IO` – для работы с файлами, сетью, БД (IO-bound)
Этот диспетчер оптимизирован для ввода-вывода (I/O): работа с файлами, сетью, БД.
import kotlinx.coroutines.*
import java.io.File

fun main() = runBlocking {
launch(Dispatchers.IO) {
val text = File("data.txt").readText()
println("Файл прочитан: $text")
}
}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Для чего нужен объект Job?

Job — это элемент управления жизненным циклом корутины. С его помощью можно:
- отменять корутину;
- отслеживать завершение;
- объединять с другими задачами;
- управлять родительскими и дочерними корутинами.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Можешь рассказать отличия и в каких случаях их использовать list set map?

В Kotlin есть три основных типа коллекций:
List — упорядоченный список элементов.
Set — множество уникальных элементов.
Map — коллекция пар "ключ-значение".

🚩List — упорядоченный список

List — это коллекция, в которой можно хранить дубликаты, а элементы доступны по индексу.
val numbers = listOf(1, 2, 3, 4, 5) // Immutable (нельзя изменять)
val mutableNumbers = mutableListOf(1, 2, 3) // Можно изменять

mutableNumbers.add(4) // Добавляем элемент
mutableNumbers.removeAt(1) // Удаляем элемент по индексу

println(mutableNumbers) // [1, 3, 4]

🚩Set — множество уникальных элементов

Set — это коллекция, в которой нет дубликатов.
val numbers = setOf(1, 2, 3, 3, 4, 5) // Дубликаты удаляются автоматически
println(numbers) // [1, 2, 3, 4, 5]

val mutableNumbers = mutableSetOf(1, 2, 3)
mutableNumbers.add(3) // Не добавится, потому что уже есть
mutableNumbers.add(4) // Добавится

println(mutableNumbers) // [1, 2, 3, 4]

🚩Map — коллекция пар "ключ-значение"

Map — это структура данных, в которой каждому ключу соответствует одно значение.
val userMap = mapOf(
1 to "Alice",
2 to "Bob",
3 to "Charlie"
) // Immutable

val mutableUserMap = mutableMapOf(1 to "Alice", 2 to "Bob")
mutableUserMap[3] = "Charlie" // Добавляем новый ключ-значение
mutableUserMap.remove(1) // Удаляем элемент по ключу

println(mutableUserMap) // {2=Bob, 3=Charlie}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Что такое Factory Builder?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 Что такое софткод?

Софткод (Softcode, Soft Coding) — это подход к программированию, при котором логика программы хранится в конфигурационных файлах, базе данных или других внешних источниках, а не жёстко (hardcoded) прописана в коде.

🚩Разница между Hardcode и Softcode

Пример Hardcode (жёстко зашито в коде)
val apiUrl = "https://api.example.com" // ❌ Если URL изменится, надо менять код

Пример Softcode (гибко через конфигурацию)
val apiUrl = Config.get("api_url") // ✅ Загружается из настроек

🚩Где используется софткод?

Конфигурационные файлы (config.json, .properties, .xml).
База данных (логика, настройки, права пользователей).
API и сервер (получение UI-элементов, бизнес-логики с сервера).
Скриптовые языки (скрипты загружаются динамически).

🚩Примеры использования Softcode в Android

Softcode через SharedPreferences (конфигурация в памяти)
val sharedPrefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val theme = sharedPrefs.getString("app_theme", "light") // ✅ Загружаем тему из настроек

Softcode через remoteConfig (Firebase Remote Config)
val minVersion = Firebase.remoteConfig.getInt("min_supported_version")

Softcode через JSON-файл (читаем конфиг из assets)
fun getConfigValue(context: Context, key: String): String {
val json = context.assets.open("config.json").bufferedReader().use { it.readText() }
val jsonObject = JSONObject(json)
return jsonObject.getString(key) // ✅ Получаем значение из JSON
}

Ставь 👍 и забирай 📚 Базу знаний


🤔 Когда происходит перегрузка при использовании inline-функций?

Перегрузка может произойти при передаче функций с разным числом аргументов, noinline и crossinline, а также при компиляции в Java, где inline-функции превращаются в разные реализации. Коллизии имён могут быть причиной перегрузки.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний


🤔 В чем разница между linked list и array list?

Являются двумя различными типами коллекций, которые используются для хранения наборов данных. Основные различия между этими двумя структурами данных касаются их внутренней реализации, что влияет на производительность операций добавления, удаления и доступа к элементам.

🚩Внутренняя реализация

🟠ArrayList
основан на динамическом массиве. Это позволяет обеспечить быстрый доступ к элементам по индексу, поскольку адрес каждого элемента в памяти может быть вычислен напрямую. Однако, поскольку внутренний массив имеет фиксированный размер, при его переполнении необходимо выделить массив большего размера и скопировать в него все элементы из старого массива, что делает операции добавления и удаления более затратными по времени, особенно для больших объемов данных.

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

🚩Производительность:

🟠ArrayList
Быстрый доступ к элементам по индексу. Медленные операции добавления и удаления элементов (особенно в начале и середине списка), так как может потребоваться сдвиг оставшейся части массива.

🟠LinkedList
Быстрые операции вставки и удаления элементов, поскольку они требуют только изменения ссылок. Медленный доступ к элементам по индексу, так как для доступа к элементу необходимо пройти по списку.

Ставь 👍 и забирай 📚 Базу знаний


🤔 Если профайлер показывает тебе что какой-нибудь фрейм занял 120 миллисекунд, что это значит?

Если профайлер показывает, что рендеринг какого-либо фрейма занял 120 миллисекунд, это означает, что этот фрейм выполнялся слишком долго, что приводит к фризам и лагам в пользовательском интерфейсе.

🚩Разбор проблемы

🟠Что значит "фрейм" в этом контексте?
В Android интерфейс обновляется 60 раз в секунду (частота 60 FPS). Это значит, что каждый кадр (фрейм) должен рендериться не дольше 16,67 мс (1000 мс / 60 FPS).

🟠Почему 120 мс — это плохо?
Если рендеринг кадра занимает 120 мс, то за это время устройство должно было бы нарисовать 7 кадров (120 / 16,67 ≈ 7). Однако оно успело обработать только один, что приводит к заметному подтормаживанию.

🟠Что может вызывать такие задержки?
Тяжёлые вычисления в основном потоке (UI Thread) – например, сложные математические операции, работа с JSON, парсинг файлов.
Долгие операции с рендерингом – сложные векторные изображения, перегруженные Canvas.draw() или анимации.
Синхронные вызовы I/O (чтение файлов, базы данных, сети) – если, например, в onDraw() идёт обращение к диску или базе данных.
Неоптимальный layout – глубокая иерархия ViewGroup, частые перерасчёты макетов (measure/layout).

🚩Как исправить?

🟠Перенести тяжёлые вычисления в фоновый поток
Coroutines, Executors, WorkManager
🟠Использовать профайлер Android Studio
для поиска "узких мест".
🟠Оптимизировать рендеринг
избегать сложных onDraw(), использовать ViewStub, RecyclerView.
🟠Пересмотреть макет
убрать ненужные ViewGroup, использовать ConstraintLayout.

Ставь 👍 и забирай 📚 Базу знаний


🤔 Перечислите маркерные интерфейс?

Маркерные интерфейсы не содержат методов, но обозначают поведение объекта.
Примеры в Java:
- Serializable — объект можно сериализовать.
- Cloneable — объект можно клонировать.
- Remote — используется для удалённых вызовов.
- RandomAccess — для коллекций с быстрым доступом по индексу.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний

Показано 20 последних публикаций.