Сервисы предназначены для выполнения длительных или фоновых операций, не требующих взаимодействия с пользователем. Они работают в фоновом режиме и могут выполнять различные задачи, даже когда пользовательский интерфейс приложения не активен или когда приложение закрыто. Вот несколько ключевых аспектов, для которых могут быть использованы сервисы:
Несмотря на свою полезность, сервисы могут быть ресурсоемкими, и их использование должно быть тщательно спланировано, чтобы минимизировать влияние на производительность устройства и продолжительность работы от батареи.
Сервисы — это компоненты, предназначенные для выполнения фоновых операций без прямого взаимодействия с пользователем. Они обеспечивают возможность выполнять длительные или ресурсоемкие задачи в фоновом режиме, позволяя основному приложению оставаться отзывчивым и эффективным.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Anonymous Quiz
2%
val length = name!.length
90%
val length = name?.length
4%
val length = name!!.length
3%
val length = name.length?
🤔3
MVVM (Model-View-ViewModel) и MVP (Model-View-Presenter) — это паттерны, используемые для разделения логики приложения на управляемые компоненты с целью упрощения разработки и обеспечения тестируемости. Хотя оба паттерна разделяют общую цель разделения ответственности в приложении, они реализуют её по-разному.
Активно взаимодействует с Presenter, который, в свою очередь, обрабатывает всю логику представления. Таким образом, Presenter напрямую управляет обновлениями View.
MVVM и MVP — это паттерны проектирования для разделения логики приложения, но они отличаются тем, как организовано взаимодействие между компонентами. MVVM использует привязку данных для автоматического обновления View, что упрощает управление интерфейсом. MVP требует, чтобы Presenter явно управлял View, что может привести к более сложному коду для управления пользовательским интерфейсом.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Anonymous Quiz
7%
lazyOf
69%
lazy
23%
lateinit
1%
deferred
Inline функции — это специальный тип функций, при компиляции которых код функции встраивается в место её вызова. Это значит, что при вызове inline функции не происходит создание нового стека вызовов; вместо этого компилятор копирует код функции непосредственно в место вызова. Этот механизм особенно полезен при использовании функций высшего порядка, которые принимают функции в качестве параметров или возвращают их в результате.
reified type parameters), что позволяет избежать ограничений, связанных с типовой стиранием во время выполнения и работать с типами как с обычными классами.inline fun <reified T> printIfTypeMatch(item: Any) {
if (item is T) {
println(item)
}
}
// Вызов функции
printIfTypeMatch<String>("Hello, inline functions!")При компиляции кода компилятор Kotlin "встраивает" код функции
printIfTypeMatch в место её вызова, избегая создания объекта для лямбды и вызова функции во время выполнения.Inline функции — это функции, код которых встраивается непосредственно в места их вызова, что позволяет улучшить производительность и дает возможность использования дополнительных языковых особенностей, таких как реифицированные типы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Anonymous Quiz
26%
extend
68%
fun
5%
ext
1%
def
👀4🤔1
Файл
AndroidManifest.xml играет роль центрального конфигурационного файла, который содержит важную информацию о приложении для Android системы. В нём объявляются основные компоненты приложения, требуемые разрешения, поддерживаемые устройственные конфигурации и другие метаданные. Вот несколько ключевых аспектов, для которых он необходим:Activity, Service, BroadcastReceiver, и ContentProvider. Для каждого из этих компонентов можно указать дополнительные настройки, например, интент-фильтры для Activity, которые определяют, какие интенты они могут обрабатывать.AndroidManifest.xml указываются эти разрешения с помощью элемента <uses-permission>.<uses-feature> и <uses-library>.Activity может объявить, что оно способно обрабатывать интенты для просмотра веб-страниц.AndroidManifest.xml является ключевым файлом в Android-приложениях, который информирует систему о структуре приложения, его компонентах, требуемых разрешениях, поддерживаемых функциях и других важных настройках, необходимых для правильной интеграции приложения в экосистему Android.Please open Telegram to view this post
VIEW IN TELEGRAM
Anonymous Quiz
21%
Уменьшает размер байт-кода
6%
Повышает читабельность
32%
Исключает выделение анонимных объектов
41%
Оптимизирует производительность
🤔11👍1🤯1
Корутины — это мощный инструмент для асинхронного программирования, позволяющий писать асинхронный код почти так же просто и понятно, как и синхронный. Они облегчают выполнение таких задач, как асинхронный ввод-вывод, длительные вычисления и работу с сетью, не блокируя основной поток и не усложняя код избыточной вложенностью и обратными вызовами.
Ключевые компоненты:
Dispatchers.IO предназначен для ввода-вывода, Dispatchers.Main используется для взаимодействия с пользовательским интерфейсом.launch и async, последняя из которых позволяет получить результат асинхронной операции.import kotlinx.coroutines.*
fun main() = runBlocking { // Создает корутину верхнего уровня
launch { // Запускает новую корутину внутри блока runBlocking
delay(1000L) // Неблокирующая задержка на 1 секунду (1000 миллисекунд)
println("World!") // Печать после задержки
}
println("Hello,") // runBlocking ждет, пока вложенная корутина не завершится
}
Этот код демонстрирует запуск корутины с использованием
launch, которая выводит "Hello," немедленно, затем ждет секунду перед выводом "World!".Корутины — это мощный инструмент для асинхронного программирования, позволяющий писать асинхронный код более просто и натурально, без блокирования потоков и упрощения управления асинхронными операциями.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Anonymous Quiz
64%
fun <T> example(param: T): T
25%
fun example<T>(param: T): T
7%
fun example(param: T)<T>: T
5%
<T> fun example(param: T): T
HashMap — это структура данных, которая использует хеш-таблицу для хранения пар "ключ-значение". Она позволяет выполнять операции вставки, удаления и поиска элементов с почти постоянным временем выполнения, что делает её очень эффективной для определённых задач. Вот как она работает:
HashMap использует хеш-функцию для вычисления хеш-кода ключа. Хеш-код затем используется для определения индекса в массиве, где будет храниться значение. Это позволяет быстро находить значения по ключам.HashMap разрешает такие коллизии, сохраняя эти элементы в одной "корзине" или "ячейке" в виде списка (до Java 8 использовались связанные списки, начиная с Java 8 — сбалансированные деревья при большом количестве коллизий в одной корзине).HashMap вычисляет индекс корзины для ключа и помещает значение в эту корзину. При поиске значения по ключу HashMap снова вычисляет индекс, находит соответствующую корзину и затем перебирает элементы в ней, чтобы найти нужное значение.HashMap достигает определённого порога заполнения (загрузки), размер массива увеличивается, и все существующие элементы перераспределяются в новом массиве. Это необходимо для поддержания эффективности операций вставки и поиска.Представьте, что у вас есть
HashMap, где ключи — это имена пользователей, а значения — это их email. Когда вы добавляете новую пару "ключ-значение" ("John Doe", "[email protected]"), HashMap выполняет следующие действия:"John Doe"."[email protected]" в корзину этого индекса.Когда вы пытаетесь найти email по имени
"John Doe", HashMap снова вычисляет хеш-код для "John Doe", находит соответствующую корзину и возвращает сохранённый в ней email.HashMap — это структура данных, использующая хеш-таблицу для эффективного хранения и поиска пар "ключ-значение". Она вычисляет хеш-коды ключей для быстрого нахождения значений, разрешает коллизии и автоматически масштабируется для поддержания своей эффективности.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Anonymous Quiz
10%
0
38%
1
8%
Множественные
44%
Зависит от контекста
🤔4👍1
Существуют специальные типы Any, Unit и Nothing, которые имеют уникальные цели и применения в языке программирования:
Object. Любой объект, за исключением null, наследуется от Any. Этот тип обычно используется там, где требуется представление любого возможного значения, за исключением null. Any определяет несколько базовых методов, таких как equals(), hashCode() и toString(), которые могут быть переопределены.fun printAnyObject(obj: Any) {
println(obj.toString())
}void, но в отличие от void, он является полноценным объектом. Функции в Kotlin, которые не возвращают значимый результат, на самом деле возвращают Unit. Этот тип обычно используется для указания, что функция выполняет действие, но не возвращает значение. Хотя возвращаемый тип Unit обычно опускается, его можно указать явно.fun printHello(): Unit {
println("Hello, World!")
}fun failWithErrorMessage(message: String): Nothing {
throw IllegalArgumentException(message)
}Использование
Nothing полезно для анализа потока выполнения программы, поскольку компилятор распознает, что код после вызова функции, возвращающей Nothing, никогда не будет выполнен.Any — это базовый тип для всех объектов в Kotlin, кроме null.Unit указывает, что функция не возвращает полезное значение, аналогично void в других языках программирования, но является объектом.Nothing используется для обозначения "невозможности" выполнения кода после определённой точки, например, после выброса исключения.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Anonymous Quiz
18%
async
3%
await
67%
suspend
12%
coroutine
😁2🤯2👾1
Класс Nothing имеет уникальное и очень специфическое назначение. Он представляет тип, который не имеет значений и используется для обозначения операций, которые никогда не завершаются нормально. Вот несколько ключевых причин, почему данный тип полезен:
Nothing ясно демонстрирует этот намеренный аспект поведения функции.Nothing, для вывода о том, что последующий код недостижим. Это может помочь в оптимизации кода и предотвращении ошибок.fun throwError(message: String): Nothing {
throw IllegalArgumentException(message)
}В этом случае он указывает, что после вызова
throwError выполнение текущей функции не будет продолжено. Это позволяет компилятору правильно анализировать поток выполнения программы и разработчикам легче понять поведение кода.Nothing — это тип без значений, который используется для обозначения операций, не имеющих нормального завершения. Это предоставляет дополнительные возможности для управления потоком выполнения программы, статического анализа и улучшения понимания кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Anonymous Quiz
12%
convert
15%
transform
58%
map
16%
cast
🤯2
Сериализация – это процесс преобразования объекта в поток байтов для сохранения его состояния или передачи его через сеть. Это нужно, чтобы можно было хранить объекты в файлы, базы данных или передавать их между разными компонентами приложения или даже разными приложениями.
Когда мы работаем с объектами в приложении, они находятся в оперативной памяти. Но, если нужно сохранить состояние объекта между запусками программы или передать его через сеть, нам нужно как-то его "упаковать". Вот тут и приходит на помощь сериализация. Например, вы можете сериализовать объект, сохранить его в файл, а потом прочитать этот файл и десериализовать объект обратно.
В Android для сериализации часто используется интерфейс
Serializable или Parcelable. Вот пример использования Serializable:import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// геттеры и сеттеры
}
Чтобы сериализовать объект
User и сохранить его в файл, можно сделать так:User user = new User("John", 30);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"))) {
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
}Для десериализации объекта из файла:
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"))) {
User user = (User) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}Parcelable предпочтительнее в Android, так как он быстрее работает по сравнению с Serializable.import android.os.Parcel;
import android.os.Parcelable;
public class User implements Parcelable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
protected User(Parcel in) {
name = in.readString();
age = in.readInt();
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
// геттеры и сеттеры
}
Теперь можно передавать объект
User между активити:Intent intent = new Intent(this, AnotherActivity.class);
User user = new User("John", 30);
intent.putExtra("user", user);
startActivity(intent);
И получить его в
AnotherActivity:User user = getIntent().getParcelableExtra("user");Сериализация – это способ сохранения или передачи объектов, преобразовывая их в поток байтов. В Android можно использовать
Serializable или Parcelable для этих целей.Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Anonymous Quiz
70%
private constructor
8%
private init
16%
private class
6%
private fun
Подключение
BroadcastReceiver в Android состоит из двух основных шагов: создание самого ресивера и его регистрация. Ресивер можно зарегистрировать как статически в манифесте, так и динамически в коде.Создадим простой
BroadcastReceiver, который будет реагировать на определённое событие, например, на получение SMS.import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Сообщение получено!", Toast.LENGTH_SHORT).show();
}
}
Можно зарегистрировать ресивер в файле
AndroidManifest.xml. Это удобно, когда вы хотите, чтобы ресивер всегда был активен и слушал определённые системные события, например, перезагрузку устройства или получение SMS.<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
</manifest>
Иногда нужно регистрировать ресивер только на время выполнения определённой активности или службы. В этом случае лучше использовать динамическую регистрацию.
import android.content.IntentFilter;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myBroadcastReceiver = new MyBroadcastReceiver();
}
@Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(myBroadcastReceiver, filter);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(myBroadcastReceiver);
}
}
В этом примере ресивер регистрируется в методе
onStart() и отписывается в методе onStop(). Это позволяет ресиверу быть активным только тогда, когда активность видима.Чтобы подключить
BroadcastReceiver, создайте его и зарегистрируйте либо в манифесте, либо в коде. Статическая регистрация через манифест делает ресивер активным всегда, а динамическая регистрация в коде позволяет контролировать время его активности.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥4
Anonymous Quiz
5%
Int
28%
String
53%
Boolean
14%
Long
🤯3