Sobes.tech
Middle+

MVI memarlığında saxlanılmaması lazım olan hadisələri necə idarə etmək olar?

sobes.tech Süni İntellekt

AI-dan cavab

MVI-də təkrarolunmaz hadisələrin (məsələn, toast göstərilməsi, naviqasiya) işlənməsi üçün, View və ya vəziyyətdə yenidən yaradılmasına ehtiyac olmayan müxtəlif yanaşmalar istifadə olunur:

  1. Side Effects (SingleLiveEvent / Channels):

    ViewModel-dən View-ə hadisələrin göndərilməsi üçün xüsusi mexanizm. SingleLiveEvent (köhnə layihələrdə və ya androidx.lifecycle:lifecycle-livedata-ktx kimi kitabxanalarda), və ya Flow-dan Channel (müasir layihələrdə). Bu, hadisənin yalnız bir dəfə qəbul ediləcəyini təmin edir.

    // Flow və Channel ilə ViewModel
    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() {
            // Biznes loqika...
            viewModelScope.launch {
                _sideEffect.send(SideEffect.ShowToast("Əməliyyat uğurla tamamlandı!"))
            }
        }
    }
    
    sealed class SideEffect {
        data class ShowToast(val message: String) : SideEffect()
        object NavigateNext : SideEffect()
    }
    
    // View-də (Fragment/Activity) SideEffect-ə qulaq asırıq
    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 göstərmənin həyata keçirilməsi
        }
    
        private fun navigateToNextScreen() {
            // Nəqliyyatın həyata keçirilməsi
        }
    }
    
  2. Yeganə istifadə hadisələri vəziyyətdə:

    Daha az tövsiyə olunan, lakin bəzən sadə hallarda istifadə olunan yanaşma. UiState-ə yeganə hadisəni göstərən bayraq və ya sahə əlavə edilir. View-də hadisə işlənəndən sonra, ViewModel-ə yeni Intent göndərilir ki, bu bayraq və ya sahə sıfırlansın. Bu, loqikanı çətinləşdirə və yanlış idarəetmə və ya yenidən yaradılma zamanı hadisənin təkrarlanmasına səbəb ola bilər.

    // Yeganə bayraq ilə vəziyyət nümunəsi
    data class MyUiState(
        val data: List<Item> = emptyList(),
        val isLoading: Boolean = false,
        val showSuccessToast: Boolean = false // Yeganə hadisə üçün bayraq
    )
    
    // ViewModel-də uğurlu əməliyyat
    fun processSuccess() {
        _uiState.update { it.copy(showSuccessToast = true) }
    }
    
    // View-də showSuccessToast = true işlənəndə
    if (state.showSuccessToast) {
        showToast("Uğurlu!")
        // Vacibdir: bayrağı sıfırlamaq üçün Intent göndərin
        viewModel.onToastShown()
    }
    
    // ViewModel-də bayrağı sıfırlamaq üçün
    fun onToastShown() {
        _uiState.update { it.copy(showSuccessToast = false) }
    }
    

Müasir Android ilə Flow və MVI-də ən tövsiyə olunan yanaşma - Channel vasitəsilə Side Effects istifadə etməkdir. Bu, təmiz, təhlükəsiz və proqnozlaşdırıla bilən yeganə hadisələr üçün həll yoludur.