Sobes.tech
Middle+

MVI архитектурасында сакталуусу керек эмес окуяларды кантип иштетүү керек?

sobes.tech AI

AIден жооп

Мындан ары бир жолу гана болуучу окуяларды (мисалы, тостту көрсөтүү, навигация) иштетүү үчүн, алардын View кайра түзүлбөшү же абалда сакталбашы үчүн, ар кандай ыкмалар колдонулат:

  1. Side Effects (SingleLiveEvent / Channels):

    ViewModel'ден View'га окуяларды жөнөтүү үчүн атайын механизм: SingleLiveEvent (эски долбоорлордо же androidx.lifecycle:lifecycle-livedata-ktx китепканасында), же Flow'дон Channel. Алар окуя бир жолу гана колдонулушун камсыздайт:

    // ViewModel — Flow жана Channel менен
    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() {
            // Ишкердик логикасы...
            viewModelScope.launch {
                _sideEffect.send(SideEffect.ShowToast("Иш аяктады!"))
            }
        }
    }
    
    sealed class SideEffect {
        data class ShowToast(val message: String) : SideEffect()
        object NavigateNext : SideEffect()
    }
    
    // View'да (Fragment/Activity) SideEffectке көз салуу
    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) {
            // Тостту көрсөтүү
        }
    
        private fun navigateToNextScreen() {
            // Навигацияны ишке ашыруу
        }
    }
    
  2. Бир жолу колдонулуучу окуялар күйүндө:

    Азыркы учурда көбүнчө колдонулбайт, бирок жөнөкөй учурларда колдонулат. UiState ичинде бир жолку иш-чараны көрсөтүүчү белгилөө же талаа кошулат. Viewда иш-чараны иштеткенде, ViewModel'ге жаңы Intent жөнөтүп, бул белгилөө/талааны өчүрөт. Бул логиканы кыйындатат жана туура эмес иштетүү же View кайра түзүлгөндө кайра ишке ашуусу мүмкүн:

    // Бир жолку иш-чара үчүн белгилөө менен State мисалы
    data class MyUiState(
        val data: List<Item> = emptyList(),
        val isLoading: Boolean = false,
        val showSuccessToast: Boolean = false // Бир жолку иш-чара үчүн белгилөө
    )
    
    // ViewModel'де ийгиликтүү иштен кийин
    fun processSuccess() {
        _uiState.update { it.copy(showSuccessToast = true) }
    }
    
    // Viewда showSuccessToast = true болсо
    if (state.showSuccessToast) {
        showToast("Ийгиликтүү!")
        // Маанилүү: белгилөөнү өчүрүү үчүн Intent жөнөтүү
        viewModel.onToastShown()
    }
    
    // ViewModel'де белгилөөнү өчүрүү
    fun onToastShown() {
        _uiState.update { it.copy(showSuccessToast = false) }
    }
    

Современный Android жана Flow менен иштөө үчүн эң жакшы ыкма — Channel аркылуу Side Effects колдонуу. Бул таза, коопсуз жана алдын ала көрүлүүчү чечим болуп саналат.