и посмотреть медиа
Kotlin | Вопросы собесов
и посмотреть медиа
Вопросы для Kotlin-разработчиков с ответами.
Вопросы для Kotlin-разработчиков с ответами.
AI бот для озвучки текста и клонирования голоса в Telegram. Создавай аудио с помощью нейросети быстро и просто.
Вопросы на Kotlin-собеседованиях: расширения, корутины, коллекции. С примерами кода и объяснениями для Android и backend.
🤔 Что из себя представляет Flow? Это асинхронный поток данных, который работает как List, но лениво. Особенности: - Выдает значения последовательно – одно за другим. - Не блокирует поток – работает с suspend-функциями. - Поддерживает cancel() – может быть остановлен в любой момент. - Позволяет работать с бесконечными потоками – полезно для сетевых запросов, БД, UI-событий. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Как решить проблему утечек памяти в RxJava? RxJava может вызывать утечки памяти, если подписки (Disposable) не очищаются правильно. Утечки памяти происходят, когда RxJava-события продолжают выполняться после уничтожения Activity/Fragment, удерживая ссылки на View или Context. 🚩Используем `CompositeDisposable` CompositeDisposable собирает все подписки и очищает их при onDestroy(). class MainActivity : AppCompatActivity() { private val disposables = CompositeDisposable() // Собираем подписки override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val disposable = Observable.interval(1, TimeUnit.SECONDS) .subscribe { println("Tick: $it") } disposables.add(disposable) // Добавляем подписку } override fun onDestroy() { super.onDestroy() disposables.clear() // ✅ Очищаем подписки, предотвращая утечку памяти } } 🚩Используем `autoDispose` (для Jetpack Lifecycle) Если используем Jetpack ViewModel или LifecycleOwner, можно автоматически отвязывать подписки. class MyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { Observable.interval(1, TimeUnit.SECONDS) .autoDispose(viewLifecycleOwner) // ✅ Автоочистка при `onDestroyView()` .subscribe { println("Tick: $it") } } } 🚩Используем `Disposable.dispose()` вручную Если подписка не в CompositeDisposable, её можно очистить вручную. private var disposable: Disposable? = null fun startObserving() { disposable = Observable.interval(1, TimeUnit.SECONDS) .subscribe { println("Tick: $it") } } fun stopObserving() { disposable?.dispose() // ✅ Очищаем подписку } 🚩Используем `ViewModel` + `LiveData` вместо RxJava RxJava может удерживать Activity/Fragment, вызывая утечки памяти. Лучше использовать ViewModel + LiveData! class MyViewModel : ViewModel() { private val _timer = MutableLiveData() val timer: LiveData = _timer init { Observable.interval(1, TimeUnit.SECONDS) .subscribe { _timer.postValue(it) } } } Подписка в Activity (без утечек!) viewModel.timer.observe(this) { println("Tick: $it") } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Расскажи про инициализаторы в классах в Kotlin В Kotlin инициализаторы используются для выполнения кода при создании экземпляра класса. Первичный (primary) конструктор Вторичные (secondary) конструкторы Инициализационный блок (init) 🟠Первичный конструктор Это основной способ инициализации класса в Kotlin. Он объявляется в заголовке класса. class User(val name: String, val age: Int) Если нужно выполнить дополнительную логику во время создания объекта, используют блок init: class User(val name: String, val age: Int) { init { println("Создан пользователь: $name, возраст: $age") } } 🟠Вторичные конструкторы Они объявляются с помощью constructor и нужны, если: Нужно несколько способов создания объекта. Надо вызвать другой конструктор (this(...)). class User { var name: String var age: Int constructor(name: String) { this.name = name this.age = 18 // Значение по умолчанию } constructor(name: String, age: Int) { this.name = name this.age = age } } Можно создать объект так val user1 = User("Алекс") // возраст будет 18 val user2 = User("Иван", 25) Если есть первичный конструктор, вторичный должен его вызывать через this(...) class User(val name: String, val age: Int) { constructor(name: String) : this(name, 18) } 🟠`init` vs вторичный конструктор init выполняется всегда при вызове первичного конструктора. Вторичный конструктор создаёт альтернативный способ создания объекта. class User(val name: String, val age: Int) { init { println("Создан пользователь: $name, возраст: $age") } constructor(name: String) : this(name, 18) { println("Вызван вторичный конструктор") } } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Что используешь, если нужно получить элемент или список элементов? В Kotlin есть множество удобных функций для получения одного элемента или списка элементов из коллекций (List, Set, Map). Какую функцию использовать — зависит от задачи. 🚩Получение одного элемента 🟠`get(index)` и `getOrNull(index)` получение по индексу Если индекс может выйти за границы массива, лучше использовать getOrNull(). val list = listOf("A", "B", "C") println(list[1]) // "B" println(list.getOrNull(5)) // null 🟠`first()` и `last()` первый и последний элементы println(list.first()) // "A" println(list.last()) // "C" Используйте firstOrNull() или lastOrNull(), если список может быть пустым println(emptyList().firstOrNull()) // null 🟠`find {}` и `findLast {}` поиск по условию Возвращает первый или последний элемент, удовлетворяющий условию. val numbers = listOf(10, 20, 30, 40) println(numbers.find { it > 15 }) // 20 println(numbers.findLast { it > 15 }) // 40 println(numbers.find { it > 50 }) // null 🟠`single()` и `singleOrNull()` если ожидается только один элемент val oneElementList = listOf(42) println(oneElementList.single()) // 42 println(oneElementList.singleOrNull()) // 42 val emptyList = emptyList() println(emptyList.singleOrNull()) // null single() бросает исключение, если элементов нет или их больше одного. 🚩Получение нескольких элементов (списка) filter {} – фильтрация элементов по условию val numbers = listOf(1, 2, 3, 4, 5) val evenNumbers = numbers.filter { it % 2 == 0 } println(evenNumbers) // [2, 4] take(n) и takeLast(n) – первые/последние n элементов val items = listOf("a", "b", "c", "d", "e") println(items.take(3)) // [a, b, c] println(items.takeLast(2)) // [d, e] slice(indices) – получение элементов по индексам val sliced = items.slice(listOf(0, 2, 4)) println(sliced) // [a, c, e] map {} – преобразование списка val squared = numbers.map { it * it } println(squared) // [1, 4, 9, 16, 25] Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Что такое лямбды с точки зрения синтаксиса в Java и Kotlin? Лямбда-выражения представляют собой компактный способ представления анонимных функций, который особенно полезен для создания коротких блоков выполнения кода, предназначенных для последующей передачи другим функциям. Лямбды широко используются для упрощения работы с коллекциями, потоками данных, асинхронным кодом и в ситуациях, где требуется функциональный интерфейс. 🚩Лямбда-выражения Были введены в Java 8 и являются частью усилий по добавлению функциональных возможностей в язык. Лямбды в Java чаще всего используются с функциональными интерфейсами, которые являются интерфейсами с одним абстрактным методом. (parameters) -> expression или (parameters) -> { statements; } 🚩Лямбда-выражения Поддерживает более гибкие и выразительные лямбды по сравнению с Java. Лямбды могут использоваться как с функциональными интерфейсами, так и в качестве части синтаксиса языка, благодаря чему Kotlin особенно удобен для функционального программирования. { parameters -> code body } 🚩Примеры Лямбда без параметров { println("Hello, World!") } Лямбда с одним параметром { a: Int -> a * a } Лямбда с несколькими параметрами { a: Int, b: Int -> a + b } Лямбда с телом, содержащим несколько выражений { s: String -> println(s) s.length } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Как называется лейаут в котором объекты могут наслаиваться друг на друга? В Android для наложения (перекрытия) элементов друг на друга используется FrameLayout или Box (в Jetpack Compose). 🚩FrameLayout (в XML и View) FrameLayout — это контейнер, в котором все вложенные элементы располагаются в левом верхнем углу, но при этом могут накладываться друг на друга. 🚩Box (в Jetpack Compose) В Jetpack Compose аналогом FrameLayout является Box. Он также позволяет располагать элементы друг над другом. Box( modifier = Modifier.fillMaxSize() ) { Image( painter = painterResource(id = R.drawable.background), contentDescription = "Фон", modifier = Modifier.fillMaxSize() ) Text( text = "Наложенный текст", fontSize = 24.sp, color = Color.White, modifier = Modifier.align(Alignment.Center) ) } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 В чем различие Default диспатчер и IO диспатчер? В Kotlin Coroutines есть несколько диспетчеров (Dispatchers), но Default и IO используются чаще всего. 🚩Главное различие: Dispatchers.Default — для тяжёлых вычислений (CPU-операции). Dispatchers.IO — для операций ввода-вывода (сеть, файлы, БД). 🟠`Dispatchers.Default` – для сложных вычислений (CPU-bound) Этот диспетчер используется, если код загружает процессор (например, сложные вычисления). import kotlinx.coroutines.* fun main() = runBlocking { launch(Dispatchers.Default) { val result = heavyComputation() println("Результат: $result") } } suspend fun heavyComputation(): Int { delay(1000) return (1..1_000_000).sum() } 🟠`Dispatchers.IO` – для работы с файлами, сетью, БД (IO-bound) Этот диспетчер оптимизирован для ввода-вывода (I/O): работа с файлами, сетью, БД. import kotlinx.coroutines.* import java.io.File fun main() = runBlocking { launch(Dispatchers.IO) { val text = File("data.txt").readText() println("Файл прочитан: $text") } } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Почему могут быть проблемы со списками в data class? В data class могут возникнуть проблемы со списками при использовании: Методов copy() – список не копируется, а передаётся по ссылке. Методов equals() и hashCode() – List сравнивается по элементам, что может быть медленно. Mutable списков (MutableList) – изменения внутри списка изменяют все копии объекта. 🚩Проблема `copy()` – список не клонируется data class User(val name: String, val tags: List) fun main() { val original = User("Alice", listOf("Admin", "Editor")) val copy = original.copy() // ✅ Поверхностное копирование println(original.tags === copy.tags) // true (один и тот же объект) } Используем toList(), чтобы создать новый неизменяемый список: fun main() { val original = User("Alice", listOf("Admin", "Editor")) val copy = original.copy(tags = original.tags.toList()) println(original.tags === copy.tags) // false (разные объекты) } 🚩`equals()` и `hashCode()` могут работать медленно data class Message(val id: Int, val content: String, val tags: List) fun main() { val message1 = Message(1, "Привет", listOf("important", "urgent")) val message2 = Message(1, "Привет", listOf("important", "urgent")) println(message1 == message2) // true (сравнивает элементы списка) } Если идентификатор (id) уникален, сравнивать только его data class Message(val id: Int, val content: String, val tags: List) { override fun equals(other: Any?) = other is Message && this.id == other.id override fun hashCode() = id.hashCode() } 🚩`MutableList` в `data class` – неожиданные изменения data class Task(val name: String, val subtasks: MutableList) fun main() { val original = Task("Купить продукты", mutableListOf("Хлеб", "Молоко")) val copy = original.copy() // ✅ Поверхностная копия copy.subtasks.add("Яйца") // ❌ Меняет список в обоих объектах! println(original.subtasks) // [Хлеб, Молоко, Яйца] println(copy.subtasks) // [Хлеб, Молоко, Яйца] } Создаём новый MutableList внутри copy() data class Task(val name: String, val subtasks: List) { fun deepCopy() = Task(name, subtasks.toMutableList()) } fun main() { val original = Task("Купить продукты", mutableListOf("Хлеб", "Молоко")) val copy = original.deepCopy() copy.subtasks.toMutableList().add("Яйца") // ✅ Теперь изменения не влияют на оригинал println(original.subtasks) // [Хлеб, Молоко] println(copy.subtasks) // [Хлеб, Молоко, Яйца] } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Какой класс можно использовать что бы ловить разные жесты? Чтобы обрабатывать жесты в Android, используйте класс GestureDetector. Он помогает отслеживать стандартные жесты: одиночные нажатия, свайпы, долгие нажатия, двойные касания и т.д. 🚩Как использовать GestureDetector? Создайте экземпляр GestureDetector, передав Context и слушателя (GestureDetector.OnGestureListener). Передавайте события касания в gestureDetector.onTouchEvent(event) из метода onTouchEvent(). class GestureActivity : AppCompatActivity(), GestureDetector.OnGestureListener { private lateinit var gestureDetector: GestureDetector override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) gestureDetector = GestureDetector(this, this) } override fun onTouchEvent(event: MotionEvent): Boolean { return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event) } override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { val deltaX = e2!!.x - e1!!.x if (deltaX > 0) Log.d("Gesture", "Swipe Right") else Log.d("Gesture", "Swipe Left") return true } override fun onDown(e: MotionEvent?) = true override fun onShowPress(e: MotionEvent?) {} override fun onSingleTapUp(e: MotionEvent?) = false override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float) = false override fun onLongPress(e: MotionEvent?) {} } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиаТолько зарегистрированные пользователи могут делиться своим мнением.
Станьте первым, кто поделится своим впечатлением об этом ресурсе!