Kā MVI arhitektūrā apstrādāt notikumus, kurus nav nepieciešams saglabāt?
sobes.tech AI
Atbilde no AI
Vienreizēju notikumu (piemēram, tosta rādīšana, navigācija), kas nedrīkst pārdzīvot View pārveidošanu vai tikt saglabāti stāvoklī, apstrādei MVI tiek izmantoti dažādi pieejas veidi:
-
Side Effects (SingleLiveEvent / Channels):
Īpašs mehānisms, kas nosūta notikumus no ViewModel uz View:
SingleLiveEvent(vecākos projektos vaiandroidx.lifecycle:lifecycle-livedata-ktxbibliotēkās), vaiChannelno Flow. Tie garantē, ka notikums tiks apstrādāts tikai vienu reizi:// ViewModel ar Flow un Channel import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.receiveAsFlow import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch class MyViewModel : ViewModel() { private val _sideEffect = Channel<SideEffect>(Channel.BUFFERED) val sideEffect = _sideEffect.receiveAsFlow() fun doSomething() { // Biznesa loģika... viewModelScope.launch { _sideEffect.send(SideEffect.ShowToast("Operācija veiksmīgi pabeigta!")) } } } sealed class SideEffect { data class ShowToast(val message: String) : SideEffect() object NavigateNext : SideEffect() } // Skats (Fragment/Activity) novēro SideEffect import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch class MyFragment : Fragment() { private val viewModel: MyViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewLifecycleOwner.lifecycleScope.launch { viewModel.sideEffect.collect { effect -> when (effect) { is SideEffect.ShowToast -> showToast(effect.message) SideEffect.NavigateNext -> navigateToNextScreen() } } } } private fun showToast(message: String) { // Tosta rādīšana } private fun navigateToNextScreen() { // Navigācija } } -
Vienreizēji notikumi stāvoklī:
Mazāk ieteicams, bet dažreiz izmanto vienkāršiem gadījumiem. Piešķiram zīmi vai lauku
UiState, kas norāda uz vienreizēju notikumu. Pēc notikuma apstrādes View, ViewModel saņem jaunuIntent, lai atiestatītu šo zīmi/lauku. Tas var sarežģīt loģiku un izraisīt atkārtotu izpildi kļūdas vai pārveidošanas laikā:// Piemērs ar stāvokli un vienreizēju zīmi data class MyUiState( val data: List<Item> = emptyList(), val isLoading: Boolean = false, val showSuccessToast: Boolean = false // Zīme vienreizējam notikumam ) // ViewModel'ā pēc veiksmīga procesa fun processSuccess() { _uiState.update { it.copy(showSuccessToast = true) } } // View'ā, ja showSuccessToast = true if (state.showSuccessToast) { showToast("Veiksmīgi!") // Svarīgi: atiestatīt zīmi, nosūtot Intent viewModel.onToastShown() } // ViewModel'ā zīmes atiestatīšana fun onToastShown() { _uiState.update { it.copy(showSuccessToast = false) } }
Mūsdienīgs Android ar Flow un MVI labākais veids — izmantot Side Effects caur Channel. Tas ir tīrs, drošs un prognozējams risinājums vienreizējiem notikumiem.