Kotlin | Вопросы собесов
2.57K subscribers
28 photos
960 links
Download Telegram
🤔 Какие есть преимущества у корутин перед RxJava?

🟠Простота и читабельность кода:
Корутины позволяют писать асинхронный код, который выглядит и читается как синхронный. Это упрощает понимание и сопровождение кода.
suspend fun fetchData(): String {
val data = networkRequest() // Выглядит как обычный синхронный вызов
return processData(data)
}

fun main() = runBlocking {
val result = fetchData()
println(result)
}

Observable<String> fetchData() {
return networkRequest()
.map(data -> processData(data));
}

fetchData()
.subscribe(result -> System.out.println(result));


🟠Управление состоянием и контекстом:
Корутины интегрированы с контекстами (например, Dispatchers), что позволяет легко переключаться между потоками и управлять жизненным циклом.
withContext(Dispatchers.IO) {
val data = networkRequest()
withContext(Dispatchers.Main) {
updateUI(data)
}
}

networkRequest()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> updateUI(data));


🟠Легкость отмены:
Корутины предоставляют простой и мощный механизм для отмены выполнения, что делает их удобными для задач, которые могут быть прерваны.
val job = launch {
val data = networkRequest()
updateUI(data)
}

// Отмена выполнения
job.cancel()

Disposable disposable = networkRequest()
.subscribe(data -> updateUI(data));

// Отмена выполнения
disposable.dispose()


🟠Меньшие накладные расходы:
Корутины, как правило, имеют меньше накладных расходов по сравнению с RxJava, поскольку они не создают объекты для каждого оператора и события.

🟠Поддержка синтаксиса языка:
Корутины являются встроенной функцией языка Kotlin, что обеспечивает лучшую интеграцию и поддержку на уровне компилятора.

🟠Потокобезопасность:
Корутины обеспечивают встроенные механизмы для работы с потоками, такие как Mutex, Channel и Flow, что упрощает написание потокобезопасного кода.
val mutex = Mutex()

suspend fun safeUpdate() {
mutex.withLock {
// Критическая секция
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111
🤔 Для чего нужны сервисы?

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

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

Intent – это механизм в Android, который используется для связи между компонентами приложения (Activity, Service, BroadcastReceiver) или для связи между различными приложениями. Он позволяет запускать новые активности, сервисы, отправлять широковещательные сообщения и передавать данные между компонентами.

🚩Почему Intent необходим

🟠Связь между компонентами
Intent используется для запуска новых экранов (Activity), фоновых процессов (Service) и широковещательных сообщений (BroadcastReceiver).
🟠Передача данных
Intent позволяет передавать данные между компонентами, что упрощает обмен информацией.
🟠Взаимодействие между приложениями
С помощью Intent можно запускать активности и сервисы других приложений, что позволяет интегрировать функционал различных приложений.

🚩Типы Intent

🟠Явный (Explicit Intent)
Используется для запуска конкретного компонента внутри приложения. Здесь явно указывается компонент, который должен быть запущен.
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);


🟠Неявный (Implicit Intent)
Используется для выполнения действий, которые могут быть выполнены несколькими приложениями. В данном случае система Android определяет, какое приложение лучше всего подходит для выполнения действия.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.example.com"));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}


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

Запуск новой Activity:
Intent intent = new Intent(this, NewActivity.class);
startActivity(intent);


Запуск Service:
Intent intent = new Intent(this, MyService.class);
startService(intent);


Отправка данных:
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("KEY_NAME", "value");
startActivity(intent);


Отправка широковещательного сообщения:
Intent intent = new Intent("com.example.CUSTOM_INTENT");
sendBroadcast(intent);


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤔 Как передавать данные из одного фрагмента в другой?

Для передачи данных между фрагментами в Android можно использовать `Bundle`, передавая данные через методы `setArguments()` и `getArguments()`. Также можно использовать интерфейсы или ViewModel, чтобы организовать взаимодействие между фрагментами через Activity. ViewModel обеспечивает безопасное и эффективное управление состоянием, особенно при работе с жизненным циклом фрагментов. Это позволяет фрагментам оставаться независимыми и легко управлять данными между ними.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2
🤔 Какие у подходa Single Activity этого подхода + и - ?

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

🚩Плюсы:

Улучшенная производительность и управление памятью:
Меньшее количество активностей означает меньше затрат на циклы жизни активностей и смену контекстов, что может улучшить производительность приложения и управление памятью.

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

Лучшая поддержка глубоких ссылок и навигации:
Навигация между экранами становится более контролируемой и удобной, особенно при использовании NavController из Android Jetpack, который оптимизирован для работы в рамках Single Activity.

Улучшенное управление состоянием:
Сохранение и восстановление состояния приложения может быть более управляемым, так как вся информация о состоянии хранится и обрабатывается в одном месте.

🚩Минусы:

Сложность управления фрагментами:
Управление множеством фрагментов, их стеками и переходами может стать более сложным и запутанным, особенно в больших и сложных приложениях.

Проблемы с производительностью:
Хотя уменьшение количества активностей может повысить производительность, управление большим количеством фрагментов и их состояниями может, напротив, ухудшить производительность, если это не контролируется должным образом.

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

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

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

Inline функции в Kotlin позволяют встраивать код функции в место её вызова, чтобы избежать накладных расходов на вызов функции, особенно в случае лямбд. Это полезно для небольших функций, которые часто вызываются и могут негативно сказаться на производительности при вызове через стек. Встраивание кода позволяет сократить расходы на создание объектов для лямбд и ускорить выполнение программы. Использование inline функций делает код более оптимизированным.

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

🟠Легковесность
Тяжелые, требуют много ресурсов ОС. Легковесные, могут существовать в большом количестве без значительных затрат.

🟠Управление выполнением
Управляются ОС, переключение контекста дорогостоящее. Управляются на уровне языка, переключение быстрое и дешевое.

🟠Модель многозадачности
Параллельное выполнение. Кооперативная многозадачность, задачи добровольно уступают управление.

🟠Обработка блокировок
Могут блокироваться на длительное время. Приостанавливаются и возобновляются, эффективны при операциях ввода-вывода.

🟠Сложность управления
Требуют сложного управления и синхронизации. Код проще и читаемее.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🤔 Для чего нужен 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