и посмотреть медиа
Kotlin | Вопросы собесов
и посмотреть медиа
Вопросы для Kotlin-разработчиков с ответами.
Вопросы для Kotlin-разработчиков с ответами.
AI бот для озвучки текста и клонирования голоса в Telegram. Создавай аудио с помощью нейросети быстро и просто.
Вопросы на Kotlin-собеседованиях: расширения, корутины, коллекции. С примерами кода и объяснениями для Android и backend.
🤔 Как с 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() } } Ставь 👍 и забирай 📚 Базу знаний
Открыть канал и посмотреть медиаТолько зарегистрированные пользователи могут делиться своим мнением.
Станьте первым, кто поделится своим впечатлением об этом ресурсе!