Sobes.tech
Middle+

MVI arxitekturasida saqlash kerak bo'lmagan voqealarni qanday boshqarish mumkin?

sobes.tech AI

AIdan javob

MVI'da bir martaba bo'lib o'tadigan voqealarni (masalan, toast ko'rsatish, navigatsiya) boshqarish uchun, ular View yoki holatni qayta yaratishdan o'tib ketmasligi uchun, turli yondashuvlar qo'llaniladi:

  1. Side Effects (SingleLiveEvent / Channels):

    ViewModel'dan View'ga voqealarni yuborish uchun maxsus mexanizm. SingleLiveEvent (eski loyihalarda yoki androidx.lifecycle:lifecycle-livedata-ktx kabi kutubxonalar), yoki Flow'dan Channel (zamonaviy loyihalarda). Ular voqea faqat bir marta iste'mol qilinishini kafolatlaydi.

    // Flow va Channel bilan 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 logika...
            viewModelScope.launch {
                _sideEffect.send(SideEffect.ShowToast("Operatsiya muvaffaqiyatli bajarildi!"))
            }
        }
    }
    
    sealed class SideEffect {
        data class ShowToast(val message: String) : SideEffect()
        object NavigateNext : SideEffect()
    }
    
    // View'da (Fragment/Activity) SideEffect'ni kuzatamiz
    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) {
            // Toastni ko'rsatish
        }
    
        private fun navigateToNextScreen() {
            // Navigatsiya
        }
    }
    
  2. Yagona foydalanish voqealari holatda:

    Kamroq tavsiya etilgan, lekin ba'zan oddiy holatlarda qo'llaniladi. UiStatega, yagona foydalanish voqeasining mavjudligini ko'rsatadigan flag yoki maydon qo'shiladi. Vaqea ishlov berilgach, View yangi Intent yuboradi, bu flag yoki maydonni holatda reset qilish uchun. Bu logikani murakkablashtirishi mumkin va noto'g'ri boshqarilsa yoki View qayta yaratilsa, takrorlanishiga olib kelishi mumkin.

    // Yagona flag bilan holat misoli
    data class MyUiState(
        val data: List<Item> = emptyList(),
        val isLoading: Boolean = false,
        val showSuccessToast: Boolean = false // Yagona voqea uchun flag
    )
    
    // ViewModel'da muvaffaqiyatli operatsiyadan so'ng
    fun processSuccess() {
        _uiState.update { it.copy(showSuccessToast = true) }
    }
    
    // View'da showSuccessToast = true bo'lsa
    if (state.showSuccessToast) {
        showToast("Muvaffaqiyat!")
        // Muhim: flagni reset qilish uchun Intent yuborish
        viewModel.onToastShown()
    }
    
    // ViewModel'da flagni reset qilish
    fun onToastShown() {
        _uiState.update { it.copy(showSuccessToast = false) }
    }
    

Zamonaviy Androidda Flow va MVI bilan eng tavsiya etilgan yondashuv — Channel orqali Side Effects foydalanish. Bu toza, xavfsiz va oldindan aytib bo'ladigan yagona voqealar uchun yechimdir.