Hogyan kezeljük az MVI architektúrában azokat az eseményeket, amelyeket nem kell menteni?
sobes.tech MI
Válasz az MI-től
Az MVI-ben az egyszeri események (például toast megjelenítése, navigáció) kezelésére, amelyek nem szabad, hogy túléljék a nézet újraalkotását vagy állapotban való tárolást, különböző megközelítéseket alkalmaznak:
-
Side Effects (SingleLiveEvent / Channels):
Egy speciális mechanizmus az események küldésére a ViewModel-ből a View-ba.
SingleLiveEvent(régebbi projektekben vagy könyvtárakban, mint azandroidx.lifecycle:lifecycle-livedata-ktx), vagyChannela Flow-ból (modern projektekben). Ezek garantálják, hogy az eseményt csak egyszer fogyasztják el.// Flow és Channel használatával a ViewModel-ben 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() { // Üzleti logika... viewModelScope.launch { _sideEffect.send(SideEffect.ShowToast("Sikeresen végrehajtva!")) } } } sealed class SideEffect { data class ShowToast(val message: String) : SideEffect() object NavigateNext : SideEffect() } // A View-ban (Fragment/Activity) figyelünk a SideEffect-re 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) { // Toast megjelenítésének implementálása } private fun navigateToNextScreen() { // Navigáció implementálása } } -
Egyszeri események állapotban:
Kevésbé ajánlott megközelítés, de néha egyszerű esetekben használják. Egy zászlót vagy mezőt adunk hozzá az
UiState-hez, ami jelzi az egyszeri esemény meglétét. Az esemény feldolgozása után a View küld egy újIntent-et a ViewModel-nek, hogy resetelje ezt a zászlót/mezőt az állapotban. Ez bonyolíthatja a logikát, és ismételt eseményt eredményezhet rossz kezelés vagy újraalkotás esetén.// Egyszeri zászlóval ellátott állapot példa data class MyUiState( val data: List<Item> = emptyList(), val isLoading: Boolean = false, val showSuccessToast: Boolean = false // Zászló az egyszeri eseményhez ) // A ViewModel-ben sikeres műveletnél fun processSuccess() { _uiState.update { it.copy(showSuccessToast = true) } } // A View-ban, amikor a showSuccessToast = true if (state.showSuccessToast) { showToast("Siker!") // Fontos: küldjön Intent-et a zászló reseteléséhez viewModel.onToastShown() } // A ViewModel-ben a zászló reseteléséhez fun onToastShown() { _uiState.update { it.copy(showSuccessToast = false) } }
A modern Android fejlesztésben Flow és MVI esetén a legjobb megközelítés a Channel-en keresztül történő Side Effects használata. Ez tiszta, biztonságos és előre jelezhető megoldás az egyszeri események kezelésére.