Kotlin | Вопросы собесов
2.57K subscribers
28 photos
962 links
Download Telegram
🤔 Для чего нужен let?

Функция let в Kotlin используется для работы с объектами в безопасном контексте. Это позволяет выполнять операции над объектами, если они не равны null. Она часто используется для работы с nullable типами, позволяя избежать явных проверок на null. Внутри блока let объект доступен через it, что позволяет элегантно обрабатывать его.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
🤔 Что быстрее, делегат или getter/setter ?

Когда речь идет о производительности, важно понимать, что делегаты и традиционные геттеры/сеттеры в Kotlin имеют разные цели и их производительность может зависеть от конкретного случая использования.

🚩Геттеры и сеттеры

Геттеры и сеттеры в Kotlin, как и в Java, это простые методы для получения и установки значений полей. Они имеют минимальный оверхед и выполняются очень быстро.
class Example {
var value: String = ""
get() = field
set(value) {
field = value
}
}


🚩Делегаты

Делегаты добавляют гибкость и позволяют переопределять поведение свойств. Однако эта гибкость имеет цену в виде дополнительного оверхеда, поскольку делегаты могут выполнять дополнительные действия (например, логирование, валидацию, уведомление об изменениях).
import kotlin.properties.Delegates

class Example {
var value: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}


🚩Сравнение производительности

🟠Геттеры и сеттеры
Минимальный оверхед, высокая производительность.
Ограниченная функциональность, жестко заданное поведение.
🟠Делегаты
Гибкость, возможность добавления дополнительной логики.
Больший оверхед из-за дополнительной логики и вызовов.

fun main() {
val exampleWithGetterSetter = ExampleGetterSetter()
val exampleWithDelegate = ExampleDelegate()

val iterations = 1_000_000

// Тест геттеров и сеттеров
var startTime = System.nanoTime()
for (i in 0 until iterations) {
exampleWithGetterSetter.value = "value"
val value = exampleWithGetterSetter.value
}
var endTime = System.nanoTime()
println("Getter/Setter time: ${(endTime - startTime) / 1_000_000} ms")

// Тест делегатов
startTime = System.nanoTime()
for (i in 0 until iterations) {
exampleWithDelegate.value = "value"
val value = exampleWithDelegate.value
}
endTime = System.nanoTime()
println("Delegate time: ${(endTime - startTime) / 1_000_000} ms")
}

class ExampleGetterSetter {
var value: String = ""
get() = field
set(value) {
field = value
}
}

class ExampleDelegate {
var value: String by Delegates.observable("<no name>") {
prop, old, new -> // Нет дополнительной логики для чистоты эксперимента
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Зачем нужен crossinline?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2👍1
🤔 Как сконфигурировать ThreadPool, чтобы все отправлялось максимально быстро?

Чтобы настроить ThreadPool для максимальной скорости отправки данных в библиотеке аналитики, необходимо учитывать характер задач (например, это CPU-bound или I/O-bound задачи), объем данных и требования к производительности. Для большинства аналитических библиотек задачи отправки данных обычно связаны с I/O-bound задачами, так как они включают сетевые операции. Поэтому необходимо создать такой ThreadPool, который оптимально справится с высокими нагрузками и обеспечит быструю отправку данных.

🚩Конфигурация ThreadPool

1⃣Используйте CachedThreadPool
Подходит для большого количества кратковременных задач. Динамически создает новые потоки по мере необходимости и повторно использует существующие потоки.
2⃣Настройка размеров пула потоков
Для I/O-bound задач: размер пула потоков должен быть больше, чем количество ядер процессора, чтобы компенсировать задержки на I/O операции.

🚩Пример конфигурации ThreadPool

1⃣Использование CachedThreadPool
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class AnalyticsThreadPool {
private final ExecutorService executorService;

private static AnalyticsThreadPool instance;

private AnalyticsThreadPool() {
// Создание CachedThreadPool для динамического управления потоками
this.executorService = Executors.newCachedThreadPool();
}

public static synchronized AnalyticsThreadPool getInstance() {
if (instance == null) {
instance = new AnalyticsThreadPool();
}
return instance;
}

public void executeTask(Runnable task) {
executorService.execute(task);
}

public void shutdown() {
executorService.shutdown();
}
}


2⃣Использование Custom ThreadPoolExecutor
Если необходим более точный контроль над параметрами пула потоков, можно использовать ThreadPoolExecutor напрямую с кастомной конфигурацией:

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

public class AnalyticsLibrary {
private final AnalyticsThreadPool threadPool;

public AnalyticsLibrary() {
this.threadPool = AnalyticsThreadPool.getInstance();
}

public void logEvent(String event) {
Runnable task = new Runnable() {
@Override
public void run() {
// Выполнение аналитической задачи
sendEventToServer(event);
}
};
threadPool.executeTask(task);
}

private void sendEventToServer(String event) {
// Логика отправки события на сервер
System.out.println("Sending event: " + event);
// Здесь может быть код для отправки HTTP запроса
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Каким образом осуществляется навигация в Android?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2
🤔 Когда система понимает, что нужно освободить ядро и передать его кому-то другому?

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

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

🟠Приоритеты задач
Задачи (процессы и потоки) могут иметь разные приоритеты. Более высокоприоритетные задачи получают больше времени на процессоре. В Android, каждый процесс и поток имеет уровень приоритета, который влияет на порядок выполнения.

🟠Временные квоты (time slices)
Временные квоты используются для распределения времени процессора между задачами. Когда задача использует свое выделенное время (time slice), планировщик может приостановить ее выполнение и переключиться на другую задачу.

🟠Состояние задачи
Задачи могут быть в разных состояниях: выполняются (running), готовые к выполнению (ready), ожидают (waiting) или заблокированы (blocked). Если задача переходит в состояние ожидания (например, ждет ввода/вывода), ядро освобождается и может быть передано другой задаче.

🚩Детали работы планировщика

🟠Приоритеты в Android
В Android приоритеты процессов управляются с помощью классов приоритетов (foreground, background, etc.). Foreground процессы (те, с которыми взаимодействует пользователь) имеют более высокий приоритет, чем background процессы.

🟠Временные квоты и контекстные переключения
Планировщик выделяет временные квоты задачам. После завершения квоты, если задача еще не завершена, планировщик приостанавливает ее и переключается на следующую задачу. Контекстные переключения происходят, когда планировщик сохраняет состояние текущей задачи и восстанавливает состояние следующей задачи.

🟠Блокировка задач
Если задача ожидает завершения операции ввода/вывода или другого события, она блокируется, и планировщик передает управление другому готовому к выполнению процессу.

🚩Пример ситуации

1⃣Выполнение Task A
Task A получает свое время на процессоре и начинает выполняться. Планировщик выделяет ей временную квоту (например, 50 миллисекунд).

2⃣Истечение времени Task A
Если Task A не завершена по истечении своей квоты, планировщик сохраняет ее состояние и переключается на другую задачу. Task B теперь получает управление и начинает выполняться.

3⃣Task A становится ожиданием
Если Task A выполняет операцию ввода/вывода и переходит в состояние ожидания, планировщик немедленно переключается на другую задачу, не дожидаясь окончания временной квоты.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Что такое лямбды с точки зрения синтаксиса в Java и Kotlin?

В Java лямбды — это упрощённый синтаксис для анонимных классов, реализующих функциональный интерфейс. Синтаксис: (параметры) -> { тело }. В Kotlin лямбды представляют собой выражения, передаваемые как функции, с синтаксисом { параметры -> тело }. Kotlin более лаконичен, позволяя опускать параметры, если их можно вывести из контекста.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍3
🤔 Как LeakCanary понимает, что произошла утечка памяти?

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

1⃣Интеграция с жизненным циклом компонентов
LeakCanary интегрируется с жизненным циклом Activity и Fragment с помощью своих наблюдателей (ActivityRefWatcher и FragmentRefWatcher). Эти наблюдатели отслеживают, когда Activity или Fragment был уничтожен и должен быть собран сборщиком мусора.

2⃣Создание слабых ссылок (WeakReference)
Когда Activity или Fragment должен быть уничтожен, LeakCanary создает слабую ссылку (WeakReference) на этот объект. Слабые ссылки позволяют сборщику мусора освободить объект, даже если на него есть слабые ссылки.
val weakReference = WeakReference(activity)


3⃣Ожидание сборки мусора (Garbage Collection)
LeakCanary инициирует сборку мусора и ждет, чтобы проверить, была ли освобождена слабая ссылка. Он вызывает метод System.gc() несколько раз, чтобы попытаться заставить сборщик мусора освободить память.
System.gc()


4⃣Проверка слабой ссылки
После вызова сборки мусора LeakCanary проверяет, является ли слабая ссылка null. Если слабая ссылка не равна null, это означает, что объект все еще удерживается в памяти и, вероятно, существует утечка памяти.
if (weakReference.get() != null) {
// Утечка памяти обнаружена
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👾1
🤔 Что такое dp?

dp (Density-independent Pixels) — это единица измерения в Android, используемая для создания адаптивных интерфейсов. Она масштабируется в зависимости от плотности экрана устройства, обеспечивая одинаковый визуальный размер элементов на разных экранах.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
🤔 Как понять, что в дампе есть утечка?

🚩Шаги анализа дампа памяти

1⃣Создание дампа памяти
Если объект не был освобожден после попыток вызвать сборку мусора, LeakCanary создает дамп памяти.

2⃣Анализ дампа
LeakCanary использует библиотеку Shark для анализа дампа памяти. Он проверяет все объекты в куче и их ссылки.

3⃣Проверка цепочки удержания
Shark проверяет, какие ссылки удерживают объект в памяти. Если объект должен был быть собран, но удерживается цепочкой ссылок, это указывает на утечку. Цепочка удержания показывает, какие объекты и ссылки не позволяют сборщику мусора освободить память.

🚩Пример цепочки удержания

1⃣Activity удерживается статическим полем
Например, если Activity удерживается статическим полем или через долгоживущий объект (например, Singleton), который не был правильно освобожден.

2⃣Анализ удерживающих ссылок
Shark анализирует пути от корневых объектов (root objects), таких как статические поля или глобальные переменные, к удерживаемому объекту.
RootObject -> Singleton -> Activity


Ставь
👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Какое главное отличие между Java и Kotlin касательно абстрактных классов и методов?

В Kotlin абстрактные классы и методы по умолчанию open, что позволяет их переопределять без явного указания модификатора open. В Java абстрактные методы всегда подразумевают переопределение, а обычные методы должны быть явно помечены abstract или final.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👀1
🤔 Как по объекту понять, что он не используется?

Сильная ссылка - это ссылка, которая напрямую указывает на объект и предотвращает его сборку сборщиком мусора.

🚩Основные подходы

🟠WeakReference
Использование слабых ссылок (WeakReference) позволяет определить, был ли объект освобожден сборщиком мусора.
🟠ObjectWatcher (в LeakCanary)
LeakCanary использует ObjectWatcher для отслеживания объектов. Если объект не освобожден, ObjectWatcher уведомляет об утечке.

import java.lang.ref.WeakReference;

public class MemoryLeakExample {

public static void main(String[] args) {
// Создание объекта
MyObject myObject = new MyObject();

// Создание слабой ссылки на объект
WeakReference<MyObject> weakRef = new WeakReference<>(myObject);

// Удаление сильной ссылки
myObject = null;

// Вызов сборщика мусора
System.gc();

// Проверка, была ли слабая ссылка освобождена
if (weakRef.get() == null) {
System.out.println("Object has been garbage collected");
} else {
System.out.println("Object is still alive");
}
}

static class MyObject {
// Некоторая логика класса
}
}


🚩Понимание, что объект не используется

🟠Нет сильных ссылок
Убедитесь, что на объект нет сильных ссылок. Только слабые, мягкие или фантомные ссылки не предотвращают сборку объекта.
🟠Сборка мусора
Если объект становится недоступным через сильные ссылки, сборщик мусора может его освободить.
🟠Проверка с помощью WeakReference
Слабые ссылки могут быть использованы для проверки того, был ли объект освобожден.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Чем отличаются единицы измерения, например, dp от sp?

dp зависит только от плотности экрана и используется для размеров интерфейса. sp (Scale-independent Pixels) дополнительно учитывает пользовательские настройки размера шрифта, что делает его предпочтительным для текстовых элементов.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2
🤔 Как LeakCanary находит ссылку на уничтоженную Activity?

Использует комбинацию слабых ссылок (WeakReference), анализ кучи и цепочек удержания, чтобы найти ссылки на уничтоженные Activity или другие объекты, которые должны были быть освобождены сборщиком мусора. Вот более подробное объяснение того, как это работает:

🚩Шаги

1⃣Создание слабой ссылки (WeakReference)
Когда Activity (или другой компонент) уничтожается, LeakCanary создает слабую ссылку на этот объект.
val weakReference = WeakReference(activity)


2⃣Ожидание сборки мусора (Garbage Collection)
LeakCanary инициирует сборку мусора, чтобы попытаться освободить уничтоженный объект.
System.gc()
System.runFinalization()


3⃣Проверка слабой ссылки
LeakCanary проверяет, освобождена ли слабая ссылка. Если объект не был освобожден, это указывает на возможную утечку памяти.
if (weakReference.get() != null) {
// Объект все еще удерживается в памяти, вероятна утечка
}


4⃣Снимок кучи (Heap Dump)
Если слабая ссылка не была освобождена, LeakCanary создает снимок кучи (heap dump) для дальнейшего анализа.
val heapDumpFile = createHeapDump()


5⃣Анализ кучи с помощью Shark
LeakCanary использует библиотеку Shark для анализа снимка кучи. Shark проверяет все объекты в куче и их удерживающие ссылки.
val heapAnalyzer = HeapAnalyzer()
val analysis = heapAnalyzer.analyze(heapDumpFile)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Не знаешь, как появились фрагменты и для чего их начали использовать?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
🤔 Как найти объект, если на него нет ссылок?

Является сложной задачей, так как такие объекты обычно собираются сборщиком мусора (GC) и освобождаются из памяти. Тем не менее, есть несколько подходов, которые могут помочь в обнаружении таких объектов в памяти, особенно при отладке или анализе утечек памяти.

🚩Шаги

1⃣Создание дампа памяти
В Android Studio можно создать дамп памяти, выбрав опцию "Dump Java heap" в профайлере.
2⃣Анализ дампа памяти
Используйте инструменты, такие как MAT (Memory Analyzer Tool) или встроенные инструменты Android Studio, чтобы проанализировать дамп памяти. Найдите объекты, которые не должны быть в памяти. Смотрите на "Unreachable objects" или "Dominators".

🚩Пример

1⃣Создание дампа памяти в Android Studio:
Откройте профайлер Android Studio и подключитесь к запущенному приложению. Нажмите "Heap Dump" для создания дампа памяти.

2⃣Анализ с помощью MAT
Откройте дамп памяти в MAT. Используйте запросы, такие как "Find Leaks" или "Top Consumers", чтобы найти объекты, которые не освобождаются.

3⃣Использование WeakReferencе
Слабые ссылки позволяют отслеживать объекты и определять, были ли они освобождены сборщиком мусора.
import java.lang.ref.WeakReference;

public class WeakReferenceExample {
public static void main(String[] args) {
MyObject myObject = new MyObject();
WeakReference<MyObject> weakRef = new WeakReference<>(myObject);

// Удаление сильной ссылки
myObject = null;

// Вызов сборщика мусора
System.gc();

// Проверка, была ли слабая ссылка освобождена
if (weakRef.get() == null) {
System.out.println("Object has been garbage collected");
} else {
System.out.println("Object is still alive");
}
}

static class MyObject {
// Некоторая логика класса
}
}


4⃣Использование инструментов для отладки памяти
Используйте специализированные инструменты для обнаружения утечек памяти и анализа использования памяти.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
🤔 В чем особенность делегатов свойств?

Делегаты в Kotlin позволяют делегировать логику управления свойствами другим объектам, что упрощает их использование. Например, lazy делегирует создание значения до первого обращения, а observable отслеживает изменения значения.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Как мы можем сохранить объект на какое-то время?

Может быть достигнуто с использованием различных подходов в зависимости от ваших требований.

🟠Использование `Handler` и `Runnable`
Вы можете использовать Handler и Runnable для отложенного выполнения задач и сохранения объекта на определенное время в памяти.

🟠Использование `CountDownTimer`
CountDownTimer может быть использован для выполнения задачи через определенное время, что может быть полезно для освобождения объекта.

🟠Использование `ScheduledExecutorService`
ScheduledExecutorService предоставляет методы для планирования задач с задержкой или периодическим выполнением.

🟠Использование `WeakReference`
Использование слабых ссылок (WeakReference) позволяет вам контролировать срок жизни объекта в памяти, но при этом объект может быть собран сборщиком мусора, если на него больше нет сильных ссылок.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как будут вести себя LinkedList и ArrayList, если вставить в них элемент?

В LinkedList вставка в начало или середину имеет сложность O(1), так как требуется только обновление ссылок, но доступ к элементу занимает O(n). В ArrayList вставка занимает O(n) из-за необходимости сдвига элементов, но доступ по индексу — O(1).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥3
🤔 Как система понимает, что WeakReference можно очистит?

Система определяет, что объект, на который ссылается WeakReference, можно очистить, используя механизм сборщика мусора (Garbage Collector, GC).

🚩Механизм работы WeakReference и GC

🟠Сильные ссылки и слабые ссылки
Сильные ссылки (Strong Reference): Объекты, на которые имеются сильные ссылки, не подлежат сборке мусора.
Слабые ссылки (Weak Reference): Объекты, на которые имеются только слабые ссылки, могут быть собраны сборщиком мусора.

🟠Создание слабой ссылки
Когда создается WeakReference, она содержит слабую ссылку на объект, позволяя GC собирать объект, даже если WeakReference все еще существует.
   MyObject myObject = new MyObject();
WeakReference<MyObject> weakRef = new WeakReference<>(myObject);


🟠Работа сборщика мусора
Определение доступности объекта: GC проверяет объекты в памяти и их ссылки. Если на объект нет сильных ссылок (только слабые), он считается недоступным и подлежит сборке.
Сборка мусора: GC освобождает память, занимаемую объектом, и удаляет записи о слабых ссылках.
Очистка WeakReference: Когда объект собирается, WeakReference автоматически очищается, и метод get() начинает возвращать null.

🟠Пример работы
После создания слабой ссылки и удаления сильной ссылки, объект становится кандидатом на сборку мусора. После вызова System.gc(), если на объект больше нет сильных ссылок, он будет собран, а WeakReference будет очищена.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1