Kuidas MVI arhitektuuris käsitleb sündmusi, mida ei ole vaja salvestada?
sobes.tech AI
Vastus AI-lt
Ühekordsed sündmused (näiteks tostide kuvamine, navigatsioon), mis ei tohiks üle elada View uuesti loomist või salvestada olekusse, töödeldakse MVI-s erinevate lähenemisviisidega:
-
Side Effects (SingleLiveEvent / Channels):
Spetsiaalne mehhanism sündmuste saatmiseks ViewModelist View'ile:
SingleLiveEvent(vanemates projektides võiandroidx.lifecycle:lifecycle-livedata-ktxteekides), võiChannelFlow'ist. Need tagavad, et sündmus käsitletakse ainult üks kord:// ViewModel Flow ja Channel'iga 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() { // Äri-logika... viewModelScope.launch { _sideEffect.send(SideEffect.ShowToast("Tegevus edukalt lõpetatud!")) } } } sealed class SideEffect { data class ShowToast(val message: String) : SideEffect() object NavigateNext : SideEffect() } // Vaates (Fragment/Activity) jälgitakse SideEffect'i 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) { // Tosti kuvamine } private fun navigateToNextScreen() { // Navigatsioon } } -
Ühekordsed sündmused olekus:
Vähem soovitatav lähenemisviis, kuid mõnikord kasutatakse lihtsates olukordades. Lisame
UiState-i märgi või välja, mis näitab ühekordset sündmust. Pärast sündmuse töötlemist View's, saadab ViewModel uueIntent, et nullida see märgistus/väli. See võib keeruliseks muuta loogikat ja põhjustada korduvat käivitamist valesti töötlemise või uuesti loomise tõttu:// Näide olekuga ja ühekordse märgisega data class MyUiState( val data: List<Item> = emptyList(), val isLoading: Boolean = false, val showSuccessToast: Boolean = false // Märk ühekordseks sündmuseks ) // ViewModel'is pärast edukat toimingut fun processSuccess() { _uiState.update { it.copy(showSuccessToast = true) } } // View's, kui showSuccessToast = true if (state.showSuccessToast) { showToast("Edukas!") // Oluline: märgi nullimiseks saada Intent viewModel.onToastShown() } // ViewModel'is märgi nullimine fun onToastShown() { _uiState.update { it.copy(showSuccessToast = false) } }
Kaasaegne Android Flow ja MVI puhul on parim lähenemine — kasutada Side Effects Channel kaudu. See on puhas, turvaline ja ennustatav lahendus ühekordsete sündmuste jaoks.