Sobes.tech
Middle+

MVI mimarisinde kaydedilmesi gerekmeyen olaylar nasıl işlenir?

sobes.tech yapay zeka

AI'dan gelen yanıt

MVI'de tek seferlik olayları (örneğin, Toast gösterme, gezinme) işlemek için, bunların View veya duruma yeniden oluşturulmadan kalmaması gereken durumlar için çeşitli yaklaşımlar kullanılır:

  1. Yan Etkiler (SingleLiveEvent / Kanallar):

    ViewModel'den View'e olay göndermek için özel bir mekanizma. SingleLiveEvent (eski projelerde veya androidx.lifecycle:lifecycle-livedata-ktx gibi kütüphanelerde) veya Flow'dan Channel (modern projelerde). Bu, olayın yalnızca bir kez tüketilmesini garanti eder.

    // Flow ve Channel ile 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() {
            // İş mantığı...
            viewModelScope.launch {
                _sideEffect.send(SideEffect.ShowToast("İşlem başarıyla tamamlandı!"))
            }
        }
    }
    
    sealed class SideEffect {
        data class ShowToast(val message: String) : SideEffect()
        object NavigateNext : SideEffect()
    }
    
    // View'da (Fragment/Activity) SideEffect izleniyor
    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österimi
        }
    
        private fun navigateToNextScreen() {
            // Navigasyon
        }
    }
    
  2. State'te Tek Kullanımlık Olaylar:

    Daha az tercih edilen bir yöntemdir, ancak bazen basit durumlarda kullanılır. UiState'e, tek kullanımlık olayın varlığını belirten bir bayrak veya alan eklenir. View'de olay işlendiğinde, View yeni bir Intent ile ViewModel'e bu bayrağı veya alanı sıfırlaması için gönderir. Bu, mantığı karmaşıklaştırabilir ve yanlış işleme veya View'un yeniden oluşturulması durumunda tekrar tetiklenmesine neden olabilir.

    // Tek kullanımlık bayrak içeren State örneği
    data class MyUiState(
        val data: List<Item> = emptyList(),
        val isLoading: Boolean = false,
        val showSuccessToast: Boolean = false // Tek kullanımlık olay bayrağı
    )
    
    // ViewModel'de başarılı işlem sonrası
    fun processSuccess() {
        _uiState.update { it.copy(showSuccessToast = true) }
    }
    
    // View'de showSuccessToast = true işlendiğinde
    if (state.showSuccessToast) {
        showToast("Başarılı!")
        // Önemli: Bayrağı sıfırlamak için Intent gönder
        viewModel.onToastShown()
    }
    
    // ViewModel'de bayrağı sıfırlama
    fun onToastShown() {
        _uiState.update { it.copy(showSuccessToast = false) }
    }
    

Modern Android'de Flow ve MVI ile en önerilen yaklaşım, Channel aracılığıyla Yan Etkiler kullanmaktır. Bu, tek seferlik olaylar için temiz, güvenli ve öngörülebilir bir çözümdür.