и посмотреть медиа
Kotlin Preguntas de Entrevista
и посмотреть медиа
Preguntas de entrevista para desarrolladores de Kotlin con respuestas.
Preguntas de entrevista para desarrolladores de Kotlin con respuestas.
bot de IA para clonar texto a voz y voz en Telegram. Cree audio utilizando la red neuronal de forma rápida y fácil.
Preguntas de entrevista Kotlin: extensiones, coroutenos, colecciones. Con ejemplos de código y explicaciones para Android y backend.
🤔 Как приложение понимает, что оно может обработать тот или иной Intent? Приложение регистрирует Intent-фильтры в манифесте (AndroidManifest.xml) или программно. Когда система отправляет Intent (например, для открытия ссылки или получения данных), она ищет среди всех зарегистрированных компонентов те, у кого: - intent-filter совпадает по action, category и data (например, MIME-тип или URI). - Компонент экспортирован (если это внешний вызов). Таким образом, Android использует фильтрацию по intent-параметрам и определяет, какие компоненты соответствуют заданному Intent. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 В каких случаях наследование полезно, а в каких нет? Это один из ключевых принципов объектно-ориентированного программирования (ООП). Оно позволяет одному классу (наследнику) унаследовать свойства и методы другого класса (родителя). Это мощный инструмент, но использовать его нужно с умом, чтобы избежать лишней сложности и проблем с поддержкой кода. 🚩Когда наследование полезно 🟠Для повторного использования кода Если у вас есть несколько классов, которые имеют общие свойства или методы, наследование позволяет вынести эти общие элементы в родительский класс. Это помогает избежать дублирования кода. open class Animal(val name: String) { fun eat() { println("$name ест.") } } class Dog(name: String) : Animal(name) { fun bark() { println("$name лает.") } } class Cat(name: String) : Animal(name) { fun meow() { println("$name мяукает.") } } // Использование: val dog = Dog("Бобик") dog.eat() // "Бобик ест." dog.bark() // "Бобик лает." 🟠Для создания иерархий классов (например, типологии) Наследование отлично подходит для задач, связанных с созданием деревьев типов или категорий. Например, у вас есть базовый класс Shape (Форма), и от него наследуются конкретные фигуры: Circle, Rectangle, Triangle. open class Shape { open fun draw() { println("Рисуется форма.") } } class Circle : Shape() { override fun draw() { println("Рисуется круг.") } } class Rectangle : Shape() { override fun draw() { println("Рисуется прямоугольник.") } } // Использование: val shapes: List = listOf(Circle(), Rectangle()) for (shape in shapes) { shape.draw() } 🟠Для использования полиморфизма Полиморфизм позволяет использовать родительские классы для работы с объектами наследников. Это полезно, если у вас есть методы, которые работают с разными типами объектов, но с единым интерфейсом. Вызов методов draw() у всех объектов, не задумываясь об их конкретном типе, благодаря полиморфизму. fun render(shape: Shape) { shape.draw() } render(Circle()) // "Рисуется круг." render(Rectangle()) // "Рисуется прямоугольник." 🟠Когда концептуально существует отношение "is-a" (является) Если наследник действительно является вариантом (подтипом) родительского класса, наследование логично. Например: Собака является животным (Dog is an Animal). Прямоугольник является фигурой (Rectangle is a Shape). 🚩Когда наследование не полезно 🟠Когда отношение "is-a" отсутствует Если объекты не имеют строгого отношения "является", наследование использовать нельзя. Например: Класс Car (Машина) и Boat (Лодка) лучше объединить через общие свойства (интерфейсы или композицию), чем делать лодку наследником машины. open class Bird { open fun fly() { println("Птица летит.") } } class Penguin : Bird() { override fun fly() { throw UnsupportedOperationException("Пингвин не умеет летать!") } } 🟠Когда нужно смешивать много разных поведений Если ваш класс должен обладать несколькими несвязанными функциями, лучше использовать композицию или интерфейсы вместо наследования. class Car : Engine, Wheels Используйте композицию: class Car { private val engine = Engine() private val wheels = Wheels() } 🟠Сложные иерархии классов Если вы создаете слишком глубокие или разветвленные иерархии, код становится сложным для понимания, тестирования и изменения. Например, изменение в базовом классе может неожиданно затронуть всех наследников. Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 В чем особенность делегатов свойств? Делегаты в Kotlin позволяют делегировать логику управления свойствами другим объектам, что упрощает их использование. Например, lazy делегирует создание значения до первого обращения, а observable отслеживает изменения значения. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Как с MVI обрабатывать события, которые не нужно хранить? В MVI (Model-View-Intent) есть проблема: события, которые не нужно хранить в State, могут повторно отобразиться при пересоздании экрана (например, при повороте экрана или навигации назад). Показ Toast / Snackbar Навигация (openScreen()) Ошибки, которые нужно показать один раз 🟠Используем `SingleLiveEvent` (для ViewModel) Это LiveData, которая отправляет событие только один раз и не пересылает его новым подписчикам. class SingleLiveEvent : MutableLiveData() { private val pending = AtomicBoolean(false) override fun observe(owner: LifecycleOwner, observer: Observer) { super.observe(owner) { value -> if (pending.compareAndSet(true, false)) { observer.onChanged(value) } } } override fun setValue(value: T?) { pending.set(true) super.setValue(value) } } ViewModel с SingleLiveEvent class MyViewModel : ViewModel() { val eventShowToast = SingleLiveEvent() fun onButtonClicked() { eventShowToast.value = "Привет, это Toast!" } } Activity/Fragment подписывается viewModel.eventShowToast.observe(viewLifecycleOwner) { message -> Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() } 🟠Используем `SharedFlow` (современный подход) В StateFlow все события хранятся в State (что не подходит для одноразовых событий). Вместо этого используем SharedFlow с replay = 0, чтобы событие не повторялось. ViewModel с SharedFlow class MyViewModel : ViewModel() { private val _events = MutableSharedFlow() val events = _events.asSharedFlow() fun onButtonClicked() { viewModelScope.launch { _events.emit(UiEvent.ShowToast("Привет, это Toast!")) } } } sealed class UiEvent { data class ShowToast(val message: String) : UiEvent() object NavigateToNextScreen : UiEvent() } Подписка в UI: lifecycleScope.launchWhenStarted { viewModel.events.collect { event -> when (event) { is UiEvent.ShowToast -> Toast.makeText(context, event.message, Toast.LENGTH_SHORT).show() is UiEvent.NavigateToNextScreen -> findNavController().navigate(R.id.nextFragment) } } } 🟠Используем `EventWrapper` (обходной путь для StateFlow) Если в State всё-таки нужно хранить событие, но не показывать его повторно, можно использовать EventWrapper. class EventWrapper(private val content: T) { private var hasBeenHandled = false fun getContentIfNotHandled(): T? { return if (hasBeenHandled) null else { hasBeenHandled = true content } } } ViewModel с StateFlow: data class UiState(val message: EventWrapper? = null) class MyViewModel : ViewModel() { private val _state = MutableStateFlow(UiState()) val state = _state.asStateFlow() fun onButtonClicked() { _state.value = UiState(message = EventWrapper("Привет, это Toast!")) } } UI подписывается и проверяет EventWrapper: viewModel.state.collect { state -> state.message?.getContentIfNotHandled()?.let { message -> Toast.makeText(context, message, Toast.LENGTH_SHORT).show() } } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Что находится внутри heap и stack? - Heap (куча): - Все объекты (class, Array, String и т.д.). - Управляется GC. - Общая для всех потоков. - Stack (стек): - Локальные переменные, параметры функций. - Контекст выполнения (фреймы вызова). - У каждого потока — свой стек. - Освобождается автоматически при выходе из функции. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Может ли потеря state быть связанной с фрагментом? Да, потеря состояния (state) может быть связана с фрагментами (Fragments) в Android. Это довольно распространённая проблема, особенно при работе с динамическими интерфейсами. Давайте разберёмся, почему она возникает, как её предотвратить и какие решения существуют. 🚩Почему происходит потеря состояния во фрагментах? 🟠Жизненный цикл фрагмента Фрагменты имеют сложный жизненный цикл, который тесно связан с активностью. Основные этапы: onCreate() — создаётся фрагмент, инициализируются объекты. onViewCreated() — создаётся View (UI компоненты). onStart() / onResume() — фрагмент становится видимым и активным. onPause() / onStop() — фрагмент приостанавливается. onDestroyView() — уничтожается только View (UI), но сам фрагмент всё ещё существует. onDestroy() — полностью уничтожается фрагмент. Фрагменты могут пересоздаваться системой, например, при смене ориентации экрана или нехватке памяти. Если разработчик неправильно сохраняет состояние фрагмента, оно может быть утеряно. 🟠Удаление View фрагмента системой Когда фрагмент переходит в состояние onDestroyView(), его View уничтожается, но сам объект фрагмента сохраняется. Если пользователь вернётся к этому фрагменту, View будет пересоздана, и вы потеряете все изменения, сделанные ранее, если они не сохранены явно. 🟠Проблемы с менеджером фрагментов Использование FragmentManager или FragmentTransaction с неправильными методами, такими как replace() или add(), без должного управления стэком (back stack), может привести к пересозданию или дублированию фрагментов, что вызывает потерю состояния. 🟠Проблемы с `savedInstanceState` Фрагменты, как и активности, используют механизм сохранения состояния через Bundle (в onSaveInstanceState). Если состояние не сохранено правильно, данные могут быть потеряны. 🚩Как предотвратить потерю состояния во фрагментах? 🟠Сохранение данных в `onSaveInstanceState` При уничтожении фрагмента система вызывает метод onSaveInstanceState(). Здесь вы можете сохранить важные данные в Bundle. override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString("key_text", editText.text.toString()) } При пересоздании фрагмента данные можно восстановить в onViewCreated() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val restoredText = savedInstanceState?.getString("key_text") editText.setText(restoredText) } 🟠Использование `ViewModel` Для хранения состояния, которое переживает уничтожение и пересоздание фрагмента, лучше использовать архитектурный компонент ViewModel. 1⃣Создайте ViewModel class MyViewModel : ViewModel() { val textData = MutableLiveData() } 2⃣Используйте его во фрагменте class MyFragment : Fragment() { private lateinit var viewModel: MyViewModel override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(this).get(MyViewModel::class.java) // Восстановление данных viewModel.textData.observe(viewLifecycleOwner) { text -> editText.setText(text) } // Сохранение данных при изменении editText.addTextChangedListener { viewModel.textData.value = it.toString() } } } 🟠Использование `FragmentManager` правильно При работе с фрагментами всегда добавляйте их в back stack, если вы хотите сохранить состояние. val fragment = MyFragment() parentFragmentManager.beginTransaction() .replace(R.id.fragment_container, fragment) .addToBackStack(null) .commit() Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиа🤔 Бывают ли случаи, когда нельзя использовать inline? Функции в Kotlin могут быть объявлены как `inline` для уменьшения накладных расходов при вызове функций высшего порядка. Однако, `inline` нельзя использовать, если тело функции содержит код, который не может быть встроен, например, если функция содержит рекурсивные вызовы сама на себя. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний
Открыть канал и посмотреть медиаSolo los usuarios registrados pueden compartir su opinión.
¡Sé el primero en compartir tu experiencia con este recurso!