← Назад к вопросам

Какой путь проходит Model в MVI?

2.0 Middle🔥 284 комментариев
#Производительность и оптимизация#Тестирование

Комментарии (4)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Путь Model в MVI (Model-View-Intent)

В архитектуре MVI (Model-View-Intent) понятие Model претерпевает значительную эволюцию по сравнению с MVP или MVVM. Здесь Model — это не просто объект данных или сущность базы данных, а единое, неизменяемое (immutable) состояние всего экрана (Screen State). Его путь — это централизованный цикл данных, который полностью описывает, что должно отображаться на UI в любой момент времени.

Жизненный цикл и путь Model

Путь Model можно описать как последовательность преобразований в строго однонаправленном потоке данных:

  1. Начальная точка: Initial State
    Модель всегда начинается с **начального состояния** (например, `LoadingState`, `EmptyState`). Это гарантирует, что у View есть валидное состояние для отображения даже до получения каких-либо данных.

```kotlin
sealed class NewsState {
    object Loading : NewsState()
    data class Content(val articles: List<Article>) : NewsState()
    data class Error(val message: String) : NewsState()
}
// Начальное состояние
private val initialState: NewsState = NewsState.Loading
```

2. Приём намерений (Intent) и создание новой Model

    Пользовательское взаимодействие (клик, swipe) или системное событие (появление экрана) порождает **Intent** — намерение изменить состояние. **Это не Android Intent, а абстракция намерения пользователя или системы.** Intent отправляется в `ViewModel` (или `Presenter`, `Interactor` — зависит от реализации).

  1. Обработка в бизнес-логике и обновление State
    В `ViewModel` Intent обрабатывается, часто с привлечением Use Cases или Репозиториев. Ключевой принцип: **на каждый Intent создаётся НОВЫЙ объект Model (State)**, а не мутируется старый. Это обеспечивает предсказуемость и упрощает отладку. Обработка часто происходит в корутинах или RxJava цепочках.

```kotlin
class NewsViewModel : ViewModel() {
    private val _state = MutableStateFlow<NewsState>(NewsState.Loading)
    val state: StateFlow<NewsState> = _state.asStateFlow()

    fun processIntent(intent: NewsIntent) {
        when (intent) {
            is NewsIntent.LoadNews -> {
                viewModelScope.launch {
                    _state.value = NewsState.Loading // Новое состояние
                    try {
                        val articles = newsRepository.getNews()
                        _state.value = NewsState.Content(articles) // Ещё одно новое состояние
                    } catch (e: Exception) {
                        _state.value = NewsState.Error(e.message ?: "Error") // Новое состояние
                    }
                }
            }
        }
    }
}
```

4. Отправка новой Model во View (рендеринг)

    Обновлённый State (новая Model) передаётся обратно во View (Activity, Fragment, Composable) через реактивный поток (`StateFlow`, `LiveData`, `Observable`). **Функция View — это «рендеринг» состояния:** она просто отображает полученную Model.

```kotlin
// В Fragment или Activity
viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.state.collect { state ->
            render(state) // Функция, которая рисует UI на основе State
        }
    }
}

private fun render(state: NewsState) {
    when (state) {
        is NewsState.Loading -> showProgressBar()
        is NewsState.Content -> showNews(state.articles)
        is NewsState.Error -> showError(state.message)
    }
}
```

5. Завершение цикла

    После рендеринга цикл замыкается. UI отображает текущее состояние и ждёт нового пользовательского взаимодействия, которое породит следующий Intent, и путь Model начнётся заново.

Ключевые особенности пути Model в MVI

  • Однонаправленный поток данных: Intent -> ViewModel -> New State -> View -> Render. Данные текут только в одном направлении, что минимизирует побочные эффекты.
  • Неизменяемость (Immutability): State (Model) — это data class или sealed class, который никогда не меняется после создания. Любое изменение — это создание новой копии.
  • Предсказуемость и воспроизводимость: Состояние экрана полностью определяется Model. Зная последовательность Intents, можно точно воспроизвести всю цепочку состояний, что невероятно полезно для отладки и тестирования.
  • Единый источник истины (Single Source of Truth): Вся информация для отрисовки UI содержится в одном объекте State. Нет конфликта между данными в разных полях или LiveData.

Таким образом, путь Model в MVI — это непрерывный, циклический процесс трансформации: Initial State -> User Intent -> Business Logic -> New Immutable State -> UI Render. Model выступает в роли «снимка» (snapshot) UI в конкретный момент времени, а её путь — это сердце однонаправленной архитектуры, обеспечивающей чистоту, тестируемость и надёжность кода.