Kotlin | Вопросы собесов
2.57K subscribers
28 photos
961 links
Download Telegram
🤔 Что означает в Android-разработке подход Single Activity?

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

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

🚩Абстрактные классы

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

🚩Особенности абстрактных классов

🟠Абстрактный класс может содержать как абстрактные, так и не абстрактные (реализованные) методы.
🟠Абстрактные методы не имеют тела и должны быть реализованы в подклассах.
🟠Абстрактный класс может наследоваться любым количеством подклассов.
🟠Абстрактные классы используются, когда нужно создать базовый класс, который определяет общие свойства и методы для своих подклассов.
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 класса могут быть абстрактными или конкретными (не абстрактными). 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
👍81
🤔 Что такое interface и чем он отличается от абстрактного класса?

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

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

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

🚩Концепции

🟠Executor Interface
Базовый интерфейс, который имеет один метод execute(Runnable command), предназначенный для выполнения переданной задачи.

🟠ExecutorService Interface
Расширяет интерфейс Executor и добавляет методы для управления жизненным циклом исполнителя, такие как shutdown(), submit(), и другие. Он также предоставляет методы для выполнения задач, возвращающих результат (Callable).

🟠ThreadPoolExecutor
Одна из самых часто используемых реализаций 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 потоков.
🟠5 задач добавляются в очередь на выполнение.
🟠Метод shutdown инициирует упорядоченное завершение работы, при котором ранее отправленные задачи будут выполнены, но новые задачи приниматься не будут.
🟠Метод awaitTermination ожидает завершения всех задач в течение указанного времени, после чего вызывается shutdownNow для принудительного завершения всех задач.

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

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

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

🟠Минимизируйте использование статических переменных.
🟠Избегайте утечек памяти, правильно управляя ссылками на контексты и активности.
🟠Используйте слабые ссылки (WeakReference) для больших объектов.
🟠Избегайте внутренних классов в Activity, заменяя их статическими вложенными классами.
🟠Применяйте LruCache для кэширования данных в памяти.
🟠Профилируйте приложение с помощью Android Studio Profiler и LeakCanary.
🟠Используйте Glide или Picasso для загрузки и кэширования изображений.
🟠Управляйте крупными объектами и загружайте изображения оптимального размера.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Расскажи data классы и sealed классы.

Data классы в Kotlin предназначены для хранения данных и автоматически генерируют методы, такие как equals(), hashCode(), toString() и copy(). Они идеально подходят для создания POJO/POCO объектов.
Sealed классы используются для представления ограниченного набора типов, похожих на перечисления, но с возможностью иметь классы с разными свойствами и методами. Это помогает обеспечить безопасное использование при работе с типами во время компиляции, улучшая обработку ошибок и логику ветвления.

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

🟠`onCreate(Bundle savedInstanceState)`
Создание активности. Вызывается при создании активности. Здесь инициализируются основные компоненты (например, настройка пользовательского интерфейса).

🟠`onStart()`
Активность становится видимой для пользователя. Вызывается после onCreate и каждый раз, когда активность становится видимой.

🟠`onResume()`
Активность становится доступной для взаимодействия с пользователем. Вызывается после onStart и каждый раз, когда активность возвращается на передний план (например, после паузы).

🟠`onPause()`
Активность перестает быть доступной для взаимодействия. Вызывается, когда активность переходит в состояние паузы (например, при открытии новой активности или диалога).

🟠`onStop()`
Активность становится невидимой для пользователя. Вызывается, когда активность больше не видна (например, при переходе к другой активности).

🟠`onDestroy()`
Уничтожение активности. Вызывается перед окончательным уничтожением активности. Здесь освобождаются ресурсы.

🟠`onRestart()`
Активность снова становится активной после остановки. Вызывается после onStop, перед onStart.

🟠`onSaveInstanceState(Bundle outState)`
Сохранение состояния активности. Вызывается перед уничтожением активности для сохранения ее текущего состояния.

🟠`onRestoreInstanceState(Bundle savedInstanceState)`
Восстановление состояния активности. Вызывается после onStart, если активность была ранее уничтожена и существует сохраненное состояние.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Чем launch отличается от async/await?

Функция launch в Kotlin Coroutines используется для запуска новой сопрограммы, которая выполняется параллельно остальному коду, и не блокирует поток, в котором она была вызвана. Результатом launch является Job, который представляет собой ссылку на сопрограмму.
Async используется для запуска сопрограммы, которая возвращает Deferred — промис для результата. Await используется для получения этого результата, при этом ожидание результата suspend'ит (приостанавливает) текущую сопрограмму до его получения.

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

🟠Разделение логики создания и инициализации UI
Фрагменты предназначены для повторного использования интерфейса и логики. Разделение методов 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
🤔 Расскажи как существуют и к чему привязаны фрагменты в Activity.

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

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

Выбор макета для фрагмента осуществляется в методе onCreateView с помощью LayoutInflater
override 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
🤔 Расскажи, про какие структуры данных знаешь.

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

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

Для списка из большого количества элементов следует использовать RecyclerView. Это наиболее эффективный и рекомендуемый компонент для отображения больших данных в виде списка или сетки в Android.

🚩Почему именно его?

🟠Производительность
RecyclerView использует механизм повторного использования (рециклинга) элементов, что значительно повышает производительность при работе с большими наборами данных.

🟠Гибкость
Поддержка различных компоновок через LayoutManager (например, LinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager).

🟠Анимации
Простая интеграция анимаций для добавления, удаления и перемещения элементов.

🟠Декораторы
Возможность добавления специальных эффектов и декораций, таких как разделители и отступы.

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

1⃣Добавьте RecyclerView в XML макет
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>


2⃣Создайте адаптер для RecyclerView
public 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);
}
}
}


3⃣Настройте RecyclerView в Activity или Fragment
public 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
🤔 Что означает в Android-разработке подход Single Activity?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Forwarded from Идущий к IT
Твое резюме на HeadHunter — ОК, если ты видишь это.

HeadHunter сравнивает ключевые навыки в твоем резюме и в вакансии и в момент отклика отображает, насколько % ты соответствуешь требованиям.

Специальный бейджик «Подходит по навыкам на 100%» отображается, если соответствие составляет более 60%.

Если при просмотре вакансий ты видишь такой бейджик, это значит, что список навыков в твоем резюме качественно составлен.

Это важный параметр, так как рекрутерам чаще показываются резюме с лучшим соответствием.

О том, как правильно указывать ключевые навыки и оптимизировать свое резюме я уже рассказывал в этом видео
🤔 Что позволяет делать ItemDecoration ?

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

🚩Основные возможности

🟠Добавление отступов
Вы можете добавлять отступы (margin) между элементами списка, чтобы улучшить визуальное разделение.
🟠Рисование разделительных линий
Легко добавлять разделительные линии между элементами списка, что делает его более читаемым.
🟠Настройка фона для отдельных элементов
Позволяет рисовать фоновые элементы, такие как цветные блоки или изображения, за элементами списка.

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

Добавление разделительных линий между элементами
class DividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() {

private val divider: Drawable? = ContextCompat.getDrawable(context, R.drawable.line_divider)

override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
val left = parent.paddingLeft
val right = parent.width - parent.paddingRight

val childCount = parent.childCount
for (i in 0 until childCount - 1) {
val child = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams

val top = child.bottom + params.bottomMargin
val bottom = top + (divider?.intrinsicHeight ?: 0)

divider?.setBounds(left, top, right, bottom)
divider?.draw(c)
}
}
}


Применение ItemDecoration в RecyclerView
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = MyAdapter(data)
recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))


Добавление отступов между элементами
class SpacesItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {

override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
outRect.left = space
outRect.right = space
outRect.bottom = space

// Добавляем верхний отступ только для первого элемента, чтобы избежать двойного отступа между элементами
if (parent.getChildAdapterPosition(view) == 0) {
outRect.top = space
}
}
}


Применение SpacesItemDecoration в RecyclerView
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = MyAdapter(data)
recyclerView.addItemDecoration(SpacesItemDecoration(16)) // 16 пикселей отступа


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2😁1
🤔 Расскажи data классы и sealed классы

`Data` классы в Kotlin предназначены для хранения данных и автоматически генерируют методы `equals()`, `hashCode()`, `toString()`, а также `copy()`, что упрощает работу с ними. `Sealed` классы представляют ограниченные иерархии наследования, где все возможные подклассы известны на этапе компиляции, что удобно для обработки фиксированных наборов типов. В сочетании, `data` и `sealed` классы помогают создавать типобезопасные и легко управляемые структуры данных, особенно для использования в `when` выражениях.

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

DefaultItemAnimator для стандартных анимаций
recyclerView.setItemAnimator(new DefaultItemAnimator());


Custom ItemAnimator для пользовательских анимаций
public class CustomItemAnimator extends DefaultItemAnimator {
@Override
public boolean animateRemove(RecyclerView.ViewHolder holder) {
holder.itemView.animate().alpha(0).setDuration(300).start();
return super.animateRemove(holder);
}
}
recyclerView.setItemAnimator(new CustomItemAnimator());


Анимации в Adapter для анимаций элементов
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.itemView.setAlpha(0);
holder.itemView.animate().alpha(1).setDuration(500).start();
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1👀1
🤔 Расскажи про data классы и sealed классы

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3