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

Файл AndroidManifest.xml необходим для определения ключевых компонентов приложения, таких как Activity, Service, BroadcastReceiver и ContentProvider. В манифесте указываются разрешения, необходимые приложению для выполнения определённых действий (например, доступ к интернету или файловой системе). Также он используется для определения метаданных приложения, таких как иконка, имя, версии и тема. Manifest обеспечивает взаимодействие системы Android с приложением и управляет его жизненным циклом.

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

🚩В Java:

Оператор == используется для сравнения двух переменных на равенство. Это означает, что == проверяет, указывают ли две переменные на один и тот же объект в памяти (сравнение ссылок).
String str1 = new String("hello");
String str2 = new String("hello");

if (str1 == str2) {
System.out.println("References are equal");
} else {
System.out.println("References are not equal");
}

// Output: References are not equal


В данном примере str1 == str2 вернет false, потому что str1 и str2 указывают на разные объекты в памяти, даже если их значения совпадают. Для сравнения значений строк в Java нужно использовать метод equals().
if (str1.equals(str2)) {
System.out.println("Values are equal");
} else {
System.out.println("Values are not equal");
}

// Output: Values are equal


🚩В Kotlin:

Оператор == используется для сравнения значений, а не ссылок. Это аналог метода equals() в Java. Для сравнения ссылок в Kotlin используется оператор ===. В данном примере str1 == str2 вернет true, потому что оператор == в Kotlin сравнивает значения строк. Если нужно сравнить ссылки в Kotlin, используется оператор ===.
val str1 = "hello"
val str2 = "hello"

if (str1 == str2) {
println("Values are equal")
} else {
println("Values are not equal")
}

// Output: Values are equal


Здесь obj1 === obj2 вернет false, потому что obj1 и obj2 указывают на разные объекты в памяти.
val obj1 = Any()
val obj2 = Any()

if (obj1 === obj2) {
println("References are equal")
} else {
println("References are not equal")
}

// Output: References are not equal


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥1
🤔 Как работает HashMap?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥5👀1
🤔 Что делать, если надо исправить долгий запуск приложения в legacy проекте?

1⃣Анализ и сбор данных
Использую инструменты профилирования (например, Android Profiler в Android Studio) для сбора данных о времени выполнения различных частей кода при запуске приложения. Проанализирую логи, чтобы найти узкие места и определить, какие операции занимают больше всего времени. Проверю все зависимости и библиотеки, используемые в проекте, чтобы понять, не вызывают ли они задержки.

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

3⃣Оптимизация кода
Перенесу инициализацию объектов, которые не нужны сразу, на более поздние этапы работы приложения. Использую асинхронные операции (например, с помощью Coroutines в Kotlin или AsyncTask в Java) для выполнения тяжелых задач в фоне. Оптимизирую сетевые запросы и запросы к базе данных, чтобы они выполнялись быстрее и потребляли меньше ресурсов.

4⃣Использование архитектурных подходов
Внедрение зависимостей с использованием Dagger/Hilt, что позволяет более гибко управлять инициализацией объектов. Перенос тяжелой логики из стартовой активности в фоновые сервисы или ViewModel, чтобы основной поток оставался свободным.

5⃣Кэширование данных
Использую кэширование данных, которые не нужно запрашивать каждый раз при запуске (например, данные, полученные из сети или базы данных).

6⃣Оптимизация ресурсов
Оптимизирую изображения и другие ресурсы, чтобы уменьшить их размер и, следовательно, время загрузки. Вместо тяжелых анимаций использую Lottie для уменьшения нагрузки на систему.

7⃣Регулярное тестирование и мониторинг
Внедряю автоматические тесты для регулярного тестирования производительности. Настраиваю инструменты мониторинга (например, Firebase Performance Monitoring) для отслеживания производительности приложения в реальном времени.
// Вместо выполнения сетевого запроса на главном потоке, перенесем его в IO поток
fun fetchData() {
CoroutineScope(Dispatchers.Main).launch {
val data = withContext(Dispatchers.IO) {
// Долгий сетевой запрос
apiService.getData()
}
updateUI(data)
}
}


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

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥6
🤔 Расскажи про коллизии в HashMap?

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

🚩Как работает

1⃣Хэширование ключей
При добавлении пары ключ-значение в HashMap, сначала вызывается метод hashCode() для ключа, чтобы получить его хэш-код.
2⃣Определение индекса бакета
Затем хэш-код используется для определения индекса бакета в массиве таблицы, где должна храниться эта пара.
3⃣Сравнение ключей
В бакете, который представляет собой связный список или дерево, проверяются все ключи с тем же индексом бакета, чтобы найти совпадение с помощью метода equals().

🚩Коллизии

🟠Связный список
В случае коллизии пара добавляется в связный список внутри соответствующего бакета.
Процесс добавления: Если бакет пустой, новая пара просто добавляется. Если нет, то пара добавляется в конец списка или обновляется, если ключ уже существует.
Процесс поиска: Когда требуется доступ к элементу, хэш-код снова используется для определения бакета, затем перебираются все элементы в списке и сравниваются ключи с помощью equals().

🟠Двоичное дерево (Java 8 и выше)
Когда количество элементов в одном бакете превышает определенный порог (обычно 8), связный список преобразуется в сбалансированное двоичное дерево, что улучшает производительность поиска и вставки.
Процесс добавления: Если количество коллизий превысило порог, связный список заменяется на дерево. Новые пары добавляются в дерево.
Процесс поиска: При доступе к элементам в дереве используется логарифмическое время поиска.

Пример, демонстрирующий коллизию в HashMap:
import java.util.HashMap;

public class HashMapCollisionExample {
public static void main(String[] args) {
HashMap<Key, String> map = new HashMap<>();

// Два ключа с одинаковым хэш-кодом
Key key1 = new Key("A1", 42);
Key key2 = new Key("B1", 42);

// Добавляем ключи в карту
map.put(key1, "Value1");
map.put(key2, "Value2");

// Получение значений
System.out.println(map.get(key1)); // Output: Value1
System.out.println(map.get(key2)); // Output: Value2
}
}

class Key {
private String name;
private int id;

public Key(String name, int id) {
this.name = name;
this.id = id;
}

@Override
public int hashCode() {
return id; // Искусственно создаем коллизии
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Key key = (Key) obj;
return id == key.id && name.equals(key.name);
}
}


🚩Как избежать и минимизировать

🟠Хорошая функция хэширования
Важно, чтобы метод hashCode() равномерно распределял значения, чтобы минимизировать вероятность коллизий.
🟠Расширение таблицы (Rehashing):
При превышении определенного порога заполненности (load factor), размер таблицы удваивается, и все элементы перераспределяются (rehashing).
🟠Использование подходящих структур данных
Современные реализации HashMap используют деревья вместо списков для бакетов с большим количеством элементов, что улучшает производительность при коллизиях.

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

Приоритет приложений в Android определяется в зависимости от состояния активности приложения (например, foreground, background) и использования системных ресурсов. Приложения, работающие в фоновом режиме, имеют более низкий приоритет по сравнению с активными, и могут быть завершены системой для освобождения ресурсов. Система также учитывает важность компонентов приложения, таких как сервисы или фоновая обработка данных. Высший приоритет получают приложения, взаимодействующие с пользователем в текущий момент.

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

🟠Неправильное использование ViewHolder в RecyclerView
Создание новых объектов при каждом скролле. Правильное использование ViewHolder для повторного использования представлений.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public MyViewHolder(View v) {
super(v);
textView = v.findViewById(R.id.textView);
}
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
return new MyViewHolder(v);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(myDataset[position]);
}

@Override
public int getItemCount() {
return myDataset.length;
}
}


🟠Тяжелые операции в onBindViewHolder
Загрузка изображений или обработка данных. Использование асинхронных задач и библиотек для загрузки изображений.
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(myDataset[position]);
Glide.with(holder.imageView.getContext())
.load(imageUrls[position])
.into(holder.imageView);
}


🟠Неправильная обработка изображений
Загрузка больших изображений без сжатия. Использование библиотек Glide или Picasso.
Glide.with(context)
.load(url)
.into(imageView);


🟠Неоптимизированные макеты
Сложные иерархии макетов. Использование простых макетов и ViewStub для отложенной загрузки.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/image_desc" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/sample_text" />
</androidx.constraintlayout.widget.ConstraintLayout>


🟠Частые вызовы notifyDataSetChanged
Перерисовка всего списка. Использование notifyItemInserted, notifyItemRemoved, notifyItemChanged для частичных обновлений.
adapter.notifyItemInserted(position);
adapter.notifyItemRemoved(position);


🟠Отсутствие кэширования данных
Повторная загрузка данных при каждом скролле. Кэширование данных с помощью LiveData.
LiveData<List<Item>> items = viewModel.getItems();
items.observe(this, new Observer<List<Item>>() {
@Override
public void onChanged(List<Item> items) {
adapter.setItems(items);
}
});


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 В чем разница между LinkedList и ArrayList?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥8
🤔 В чем разница между работой с list и работой с sequence ?

🚩Основные структуры работы с коллекциями

🟠List
Является жадной коллекцией, что означает, что все операции над элементами выполняются немедленно и целиком. Когда вы применяете функции к списку, такие как map, filter и т.д., все элементы проходят через каждую функцию сразу же. В данном примере все элементы списка numbers сначала умножаются на 2, затем фильтруются. Вся работа выполняется сразу для каждого элемента.
val numbers = listOf(1, 2, 3, 4, 5)
val result = numbers
.map { it * 2 }
.filter { it > 5 }
println(result) // Output: [6, 8, 10]


🟠Sequence
Является ленивой коллекцией. Это означает, что элементы обрабатываются по мере необходимости. Функции, применяемые к последовательности, создают цепочку операций, которая выполняется только при обращении к элементам. В этом примере numbers сначала преобразуется в Sequence. Операции map и filter создают цепочку, которая выполняется только при преобразовании обратно в List с помощью toList(). Это позволяет избежать лишних операций и обрабатывать элементы по мере необходимости.
val numbers = listOf(1, 2, 3, 4, 5)
val result = numbers.asSequence()
.map { it * 2 }
.filter { it > 5 }
.toList()
println(result) // Output: [6, 8, 10]


🚩Различия

🟠Жадность против ленивости
List: Все элементы обрабатываются сразу при вызове функций.
Sequence: Элементы обрабатываются по мере необходимости, что может повысить эффективность.

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

🟠Использование памяти
List: Может использовать больше памяти из-за создания промежуточных коллекций.
Sequence: Уменьшает использование памяти, обрабатывая элементы по одному.

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

`BroadcastReceiver` — это компонент Android, который позволяет приложениям принимать и обрабатывать широковещательные сообщения (broadcasts) от системы или других приложений. Примеры системных сообщений включают изменения состояния сети, получение SMS или завершение загрузки устройства. Приложения могут регистрировать BroadcastReceiver статически в манифесте или динамически в коде. BroadcastReceiver помогает реагировать на важные события, происходящие в системе.

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

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

🟠Фоновые задачи
Сервисы выполняют задачи в фоновом режиме, что позволяет не прерывать работу пользовательского интерфейса.

🟠Отсутствие UI
Сервисы не имеют пользовательского интерфейса. Они работают независимо от активности, которая может завершиться или быть приостановлена.

🟠Долгосрочные операции
Сервисы предназначены для выполнения длительных операций, которые могут продолжаться даже после закрытия приложения.

🚩Типы сервисов

🟠Started Service (Запущенный сервис)
Запускается с помощью метода startService(). Выполняет свою задачу независимо и завершает работу сам, вызвав stopSelf(), или его можно остановить извне, вызвав stopService(). Загрузка файла в фоне.
// Запуск сервиса
Intent intent = new Intent(this, MyService.class);
startService(intent);

// Остановка сервиса
stopService(intent);


🟠Bound Service (Связанный сервис)
Предоставляет интерфейс клиентам для взаимодействия с сервисом с помощью bindService(). Связывается с компонентом приложения (например, Activity), и работает до тех пор, пока компонент не завершится. Сервис для взаимодействия с удаленной базой данных.
// Привязка к сервису
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

// Отключение от сервиса
unbindService(serviceConnection);


Пример привязки к Bound Service в Activity:
public class MainActivity extends AppCompatActivity {
MyBoundService myService;
boolean isBound = false;

private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyBoundService.LocalBinder binder = (MyBoundService.LocalBinder) service;
myService = binder.getService();
isBound = true;
}

@Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};

@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MyBoundService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
super.onStop();
if (isBound) {
unbindService(serviceConnection);
isBound = false;
}
}
}


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

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

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

Он используется для обозначения кода, который никогда не завершится успешно. Понимание того, почему и как Nothing можно подставлять везде, требует изучения его особенностей и применения.

🚩Особенности типа

🟠Подтип любого типа
Nothing является подтипом любого другого типа в Kotlin. Это означает, что значение типа Nothing можно присвоить переменной любого типа.

🟠Отсутствие значения
Тип Nothing не имеет значений. Любая функция, которая возвращает Nothing, либо выбрасывает исключение, либо не завершает выполнение (например, бесконечный цикл).

🚩Применение

🟠Функции, которые не возвращают значение
Функции, которые всегда выбрасывают исключение, могут быть объявлены с возвращаемым типом Nothing.
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}


🟠Указание невозможности завершения
Тип Nothing используется для обозначения точек кода, которые не могут быть достигнуты. Например, после выбрасывания исключения выполнение кода не продолжается.
val result: Int = fail("Error occurred") // Тип Nothing может быть присвоен переменной типа Int


🟠Использование в выражениях
Nothing может быть использован в выражениях, где требуется любой тип. Это позволяет писать более выразительный и безопасный код.
fun process(value: Any?) {
val result = value ?: fail("Value is null") // fail возвращает Nothing, который совместим с любым типом
}


🟠Обработка ошибок
В некоторых случаях Nothing используется в библиотеках для обработки ошибок или в случаях, когда выполнение программы не может продолжаться.
sealed class Result<out T>
class Success<out T>(val data: T) : Result<T>()
class Error(val exception: Throwable) : Result<Nothing>() // Error использует Nothing


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

Функция, выбрасывающая исключение
fun terminate(): Nothing {
throw RuntimeException("This function never returns")
}

fun main() {
val x: Int = terminate() // Можно присвоить переменной типа Int
}


Использование Nothing в условных выражениях:
fun checkNotNull(value: String?): String {
return value ?: fail("Value is null") // Если value null, вызовется fail, возвращающий Nothing
}

fun main() {
val name: String = checkNotNull(null) // Ошибка: Value is null
}


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

`data class` в Kotlin автоматически генерирует полезные методы, такие как `equals()`, `hashCode()`, `toString()`, и `copy()`, что делает его идеальным для хранения данных. Обычные классы не предоставляют такую функциональность по умолчанию, и все эти методы должны быть реализованы вручную. Data-классы используются для создания объектов, которые содержат только данные, без сложной логики. Это сокращает количество шаблонного кода и улучшает читаемость.

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

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

🚩Неизменяемые коллекции

🟠List
Неизменяемый список, который позволяет хранить элементы в определенном порядке и допускает дублирование элементов.
val immutableList: List<String> = listOf("Apple", "Banana", "Cherry")


🟠Set
Неизменяемое множество, которое не допускает дублирования элементов и не гарантирует сохранение порядка.
val immutableSet: Set<String> = setOf("Apple", "Banana", "Cherry")


🟠Map
Неизменяемая карта, которая хранит пары ключ-значение. Ключи должны быть уникальными.
val immutableMap: Map<String, Int> = mapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)


🚩Изменяемые коллекции

🟠MutableList
Изменяемый список, который позволяет добавлять, удалять и изменять элементы.
val mutableList: MutableList<String> = mutableListOf("Apple", "Banana", "Cherry")
mutableList.add("Date")


🟠MutableSet
Изменяемое множество, которое позволяет добавлять и удалять элементы.
val mutableSet: MutableSet<String> = mutableSetOf("Apple", "Banana", "Cherry")
mutableSet.add("Date")


🟠MutableMap
Изменяемая карта, которая позволяет добавлять, удалять и изменять пары ключ-значение.
val mutableMap: MutableMap<String, Int> = mutableMapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)
mutableMap["Date"] = 4


🚩Специализированные коллекции

🟠ArrayList
Изменяемый список, основанный на массиве. Обеспечивает быстрый доступ по индексу.
val arrayList: ArrayList<String> = arrayListOf("Apple", "Banana", "Cherry")


🟠HashSet
Изменяемое множество, основанное на хэш-таблице. Обеспечивает быструю проверку принадлежности.
val hashSet: HashSet<String> = hashSetOf("Apple", "Banana", "Cherry")


🟠HashMap
Изменяемая карта, основанная на хэш-таблице. Обеспечивает быстрый доступ к значениям по ключу.
val hashMap: HashMap<String, Int> = hashMapOf("Apple" to 1, "Banana" to 2, "Cherry" to 3)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111
🤔 Что такое сборщик мусора?

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

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

🟠Правильное использование ViewHolder в RecyclerView
Причина: Создание новых объектов при каждом скролле приводит к значительным задержкам.
Решение: Используйте ViewHolder для повторного использования представлений.
class MyAdapter(private val myDataset: Array<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

class MyViewHolder(v: View) : RecyclerView.ViewHolder(v) {
val textView: TextView = v.findViewById(R.id.textView)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.my_text_view, parent, false)
return MyViewHolder(v)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
}

override fun getItemCount(): Int {
return myDataset.size
}
}


🟠Выполнение тяжелых операций в фоне
Причина: Выполнение тяжелых операций в главном потоке приводит к блокировке пользовательского интерфейса.
Решение: Переносите тяжелые операции в асинхронные задачи или используйте библиотеки для асинхронной загрузки.
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
Glide.with(holder.imageView.context)
.load(imageUrls[position])
.into(holder.imageView)
}


🟠Использование библиотек для работы с изображениями
Причина: Загрузка больших изображений в главном потоке может замедлить приложение.
Решение: Используйте библиотеки, такие как Glide или Picasso, которые автоматически обрабатывают загрузку и кэширование изображений.
Glide.with(context)
.load(url)
.into(imageView);


🟠Оптимизация макетов
Причина: Сложные иерархии макетов или невидимые представления занимают больше памяти и времени на рендеринг.
Решение: Оптимизируйте макеты, минимизируйте количество вложенных представлений и используйте ViewStub для отложенной загрузки.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:contentDescription="@string/image_desc" />

<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/imageView"
android:text="@string/sample_text" />
</androidx.constraintlayout.widget.ConstraintLayout>


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что такое принципы SOLID?

SOLID — это пять принципов объектно-ориентированного программирования, направленных на создание гибкого, поддерживаемого и расширяемого кода. Эти принципы включают: Single Responsibility (единственная ответственность), Open/Closed (открытость для расширения, закрытость для изменений), Liskov Substitution (замена Барбары Лисков), Interface Segregation (разделение интерфейсов) и Dependency Inversion (инверсия зависимостей). Применение SOLID помогает улучшить архитектуру приложений и уменьшить сложность кода.

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

🚩Главные функции стека включают основные операции для добавления, удаления и просмотра элементов.

🟠push()
Добавляет элемент на вершину стека. Эта операция вставляет новый элемент в стек и делает его верхним элементом.
val stack = Stack<Int>()
stack.push(10) // Стек: [10]
stack.push(20) // Стек: [10, 20]


🟠pop()
Удаляет и возвращает верхний элемент стека. Эта операция удаляет элемент, который находится на вершине стека, и возвращает его. Если стек пуст, обычно выбрасывается исключение (например, EmptyStackException).
val top = stack.pop() // top = 20, Стек: [10]


🟠peek()
Возвращает верхний элемент стека без его удаления. Эта операция позволяет просмотреть верхний элемент стека без его удаления. Если стек пуст, обычно выбрасывается исключение.
val top = stack.peek() // top = 10, Стек: [10]


🚩Дополнительные функции

🟠search(Object o)
Ищет элемент в стеке и возвращает его позицию относительно вершины стека. Если элемент не найден, возвращает -1.
val position = stack.search(10) // position = 1


Пример использования стека
import java.util.Stack;

public class StackExample {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();

// Добавление элементов (push)
stack.push(10);
stack.push(20);
stack.push(30);

// Просмотр верхнего элемента (peek)
System.out.println("Верхний элемент: " + stack.peek()); // Вывод: 30

// Удаление верхнего элемента (pop)
System.out.println("Удален элемент: " + stack.pop()); // Вывод: 30
System.out.println("Новый верхний элемент: " + stack.peek()); // Вывод: 20

// Проверка, пуст ли стек (isEmpty)
System.out.println("Стек пустой? " + stack.isEmpty()); // Вывод: false

// Размер стека (size)
System.out.println("Размер стека: " + stack.size()); // Вывод: 2
}
}


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