Это класс, который используется для хранения данных. Важной особенностью таких классов является автоматическая генерация некоторых методов, включая
componentN функции. Эти функции нужны для того, чтобы можно было легко получать значения свойств объекта данного класса. Здесь объявлен data class
Person с двумя свойствами: name и age. Когда создается объект person этого класса, мы можем использовать синтаксис деструктуризации для извлечения значений этих свойств. Внутренне это работает благодаря componentN функциям, которые автоматически создаются компилятором для каждого свойства. data class Person(val name: String, val age: Int)
fun main() {
val person = Person("Alice", 30)
// Использование componentN функций
val (name, age) = person
println("Name: $name, Age: $age")
}
component1 возвращает значение свойства name.component2 возвращает значение свойства age.Синтаксис деструктуризации (
val (name, age) = person) позволяет присвоить значения этих свойств соответствующим переменным, как если бы мы вручную вызывали person.component1() и person.component2().Вот как это могло бы выглядеть без синтаксиса деструктуризации:
И так, функции
componentN служат для облегчения доступа к свойствам data class, особенно при использовании синтаксиса деструктуризации.fun main() {
val person = Person("Alice", 30)
val name = person.component1()
val age = person.component2()
println("Name: $name, Age: $age")
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Data class должен иметь хотя бы один параметр в первичном конструкторе.
Параметры первичного конструктора должны быть помечены как
val или var, чтобы они становились свойствами класса.Kotlin автоматически генерирует несколько функций для data class:
equals(), hashCode(), toString(), copy(), и componentN функции для каждого свойства в порядке их объявления.Data class не может быть
abstract, open, sealed или inner.data class Person(val name: String, val age: Int)
Data class
Person имеет первичный конструктор с двумя параметрами: name и age.Параметры
name и age помечены как val, что делает их свойствами класса с доступом только для чтения.Компилятор автоматически генерирует следующие функции для класса
Person:equals(): для проверки равенства объектов.hashCode(): для вычисления хэш-кода.toString(): для представления объекта в виде строки.copy(): для создания копии объекта с возможностью изменения некоторых свойств.componentN функции: для доступа к свойствам по порядку их объявления (например, component1 для name и component2 для age).Data class
Person не может быть помечен как abstract, open, sealed или inner.fun main() {
val person1 = Person("Alice", 30)
val person2 = person1.copy(age = 31)
println(person1) // Вывод: Person(name=Alice, age=30)
println(person2) // Вывод: Person(name=Alice, age=31)
val (name, age) = person1
println("Name: $name, Age: $age") // Вывод: Name: Alice, Age: 30
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥6👾1
Это конструктор, который объявляется вместе с объявлением класса. Он может принимать параметры и инициализировать свойства класса. Этот класс
Person имеет первичный конструктор с двумя параметрами: name и age. Они одновременно являются свойствами класса.class Person(val name: String, var age: Int)
Особенности первичного конструктора.
Параметры первичного конструктора могут быть объявлены как
val или var, что делает их свойствами класса. Код инициализации может быть выполнен в блоке init.class Person(val name: String, var age: Int) {
init {
println("Person initialized with name: $name and age: $age")
}
}Это конструкторы, которые объявляются внутри класса с использованием ключевого слова
constructor. Они используются для предоставления дополнительных способов инициализации класса.class Person {
var name: String
var age: Int
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
constructor(name: String) {
this.name = name
this.age = 0 // Значение по умолчанию
}
}Этот класс
Person имеет два вторичных конструктора:Один принимает два параметра:
name и age.Другой принимает только параметр
name и устанавливает age по умолчанию в 0.Сочетание первичного и вторичных конструкторов
Класс может иметь как первичный, так и вторичные конструкторы. Если у класса есть первичный конструктор, вторичные конструкторы должны делегировать ему вызов с помощью ключевого слова
this. В этом примере вторичный конструктор делегирует вызов первичному конструктору с значением age по умолчанию равным 0.class Person(val name: String, var age: Int) {
constructor(name: String) : this(name, 0) {
println("Secondary constructor called")
}
init {
println("Primary constructor called")
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2
Это класс, который не может быть инстанцирован напрямую и может содержать абстрактные методы, которые должны быть реализованы в подклассах.
abstract class Animal {
abstract fun makeSound()
fun sleep() {
println("The animal is sleeping")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Woof")
}
}
class Cat : Animal() {
override fun makeSound() {
println("Meow")
}
}Это классы, которые ограничивают количество подклассов, которые могут их наследовать. Все возможные подклассы должны быть объявлены в том же файле, что и sealed класс.
Особенности sealed классов
Sealed классы используются для ограничения иерархии классов. Все подклассы должны быть известны на этапе компиляции. Подклассы sealed класса могут быть абстрактными или конкретными (не абстрактными). Sealed классы часто используются в сочетании с when-выражениями для обеспечения исчерпывающей проверки вариантов.
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val exception: Exception) : Result()
object Loading : Result()
}
fun handleResult(result: Result) {
when (result) {
is Result.Success -> println("Data: ${result.data}")
is Result.Error -> println("Error: ${result.exception.message}")
Result.Loading -> println("Loading...")
}
}Абстрактный класс: может наследоваться любым количеством подклассов, которые могут находиться в разных файлах и модулях.
Sealed класс: ограничивает количество подклассов, которые могут его наследовать. Все подклассы должны быть объявлены в одном файле.
Абстрактный класс: используется для создания базовых классов с общей функциональностью, которая должна быть реализована в подклассах.
Sealed класс: используется для создания ограниченных иерархий классов, когда все возможные варианты известны и должны быть исчерпывающе обработаны (например, при работе с состояниями или результатами операций).
Sealed класс: предоставляет более строгую проверку типов на этапе компиляции, что делает его удобным для использования в when-выражениях без необходимости добавления ветки else.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍1
Это интерфейс из библиотеки
java.util.concurrent, который представляет собой абстракцию для запуска задач. Он позволяет отделить создание задач от их выполнения, обеспечивая гибкость и контроль над выполнением параллельных операций.Базовый интерфейс, который имеет один метод
execute(Runnable command), предназначенный для выполнения переданной задачи.Расширяет интерфейс
Executor и добавляет методы для управления жизненным циклом исполнителя, такие как shutdown(), submit(), и другие. Он также предоставляет методы для выполнения задач, возвращающих результат (Callable).Одна из самых часто используемых реализаций
ExecutorService, которая использует пул потоков для управления выполнением задач.В этом примере создается
Executor с использованием фабричного метода Executors.newSingleThreadExecutor(), который создает одиночный поток для выполнения задач. Метод execute принимает задачу в виде объекта Runnable и выполняет её в потоке.import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("Task executed");
}
});
}
}
Более сложный пример с использованием
ExecutorService:import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
executorService.execute(new WorkerThread("Task " + i));
}
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
}
}
class WorkerThread implements Runnable {
private String command;
public WorkerThread(String command) {
this.command = command;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
processCommand();
System.out.println(Thread.currentThread().getName() + " End.");
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ExecutorService с фиксированным пулом из 3 потоков.shutdown инициирует упорядоченное завершение работы, при котором ранее отправленные задачи будут выполнены, но новые задачи приниматься не будут.awaitTermination ожидает завершения всех задач в течение указанного времени, после чего вызывается shutdownNow для принудительного завершения всех задач.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5🔥2👍1
WeakReference) для больших объектов.LruCache для кэширования данных в памяти.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Sealed классы используются для представления ограниченного набора типов, похожих на перечисления, но с возможностью иметь классы с разными свойствами и методами. Это помогает обеспечить безопасное использование при работе с типами во время компиляции, улучшая обработку ошибок и логику ветвления.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤1
Создание активности. Вызывается при создании активности. Здесь инициализируются основные компоненты (например, настройка пользовательского интерфейса).
Активность становится видимой для пользователя. Вызывается после
onCreate и каждый раз, когда активность становится видимой.Активность становится доступной для взаимодействия с пользователем. Вызывается после
onStart и каждый раз, когда активность возвращается на передний план (например, после паузы).Активность перестает быть доступной для взаимодействия. Вызывается, когда активность переходит в состояние паузы (например, при открытии новой активности или диалога).
Активность становится невидимой для пользователя. Вызывается, когда активность больше не видна (например, при переходе к другой активности).
Уничтожение активности. Вызывается перед окончательным уничтожением активности. Здесь освобождаются ресурсы.
Активность снова становится активной после остановки. Вызывается после
onStop, перед onStart.Сохранение состояния активности. Вызывается перед уничтожением активности для сохранения ее текущего состояния.
Восстановление состояния активности. Вызывается после
onStart, если активность была ранее уничтожена и существует сохраненное состояние.Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Async используется для запуска сопрограммы, которая возвращает Deferred — промис для результата. Await используется для получения этого результата, при этом ожидание результата suspend'ит (приостанавливает) текущую сопрограмму до его получения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥4
Фрагменты предназначены для повторного использования интерфейса и логики. Разделение методов
onCreate и onCreateView позволяет разделить код, связанный с настройкой фрагмента, и код, связанный с созданием и настройкой пользовательского интерфейса.onCreate: Используется для выполнения общей логики фрагмента, такой как инициализация переменных, настройка адаптеров и других объектов, которые не зависят от представления.onCreateView: Используется для создания и настройки пользовательского интерфейса фрагмента, включая инфлейтинг макета и инициализацию виджетов.Фрагменты могут использоваться в разных макетах для разных устройств (например, планшеты и телефоны) или ориентаций экрана (портретный и ландшафтный режимы). Использование
onCreateView позволяет гибко создавать и настраивать пользовательский интерфейс в зависимости от текущей конфигурации устройства.Фрагменты могут быть добавлены или заменены динамически в различных контейнерах активностей. Метод
onCreateView позволяет гибко создавать интерфейс каждый раз, когда фрагмент добавляется или заменяется.class MyFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Инициализация логики фрагмента, например, настройка адаптера
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Инфлейтинг макета для фрагмента
val view = inflater.inflate(R.layout.fragment_layout, container, false)
// Инициализация элементов пользовательского интерфейса
val textView: TextView = view.findViewById(R.id.textView)
textView.text = "Hello, World!"
return view
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Выбор макета для фрагмента осуществляется в методе
onCreateView с помощью LayoutInflateroverride fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_example, container, false)
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔3👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Для списка из большого количества элементов следует использовать
RecyclerView. Это наиболее эффективный и рекомендуемый компонент для отображения больших данных в виде списка или сетки в Android.RecyclerView использует механизм повторного использования (рециклинга) элементов, что значительно повышает производительность при работе с большими наборами данных.Поддержка различных компоновок через
LayoutManager (например, LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager).Простая интеграция анимаций для добавления, удаления и перемещения элементов.
Возможность добавления специальных эффектов и декораций, таких как разделители и отступы.
RecyclerView в XML макет<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
RecyclerViewpublic class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<String> data;
public MyAdapter(List<String> data) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
String item = data.get(position);
holder.textView.setText(item);
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public ViewHolder(View view) {
super(view);
textView = view.findViewById(R.id.textView);
}
}
}RecyclerView в Activity или Fragmentpublic class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<String> data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
data.add("Item " + i);
}
MyAdapter adapter = new MyAdapter(data);
recyclerView.setAdapter(adapter);
}
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5😁4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Forwarded from Идущий к IT
Твое резюме на HeadHunter — ОК, если ты видишь это.
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.
Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.
Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.
Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.
О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео