Что такое MVI

Ответ

MVI (Model-View-Intent) — это архитектурный паттерн, основанный на однонаправленном потоке данных. Он похож на MVVM, но строже в управлении состоянием.

Основные компоненты:

  • Model — состояние экрана (immutable data class).
  • View — отображает состояние и отправляет интенты (пользовательские действия).
  • Intent — намерения пользователя (клики, свайпы и т.д.).

Пример состояния:

data class LoginState(
    val isLoading: Boolean = false,
    val error: String? = null,
    val isSuccess: Boolean = false
)

Преимущества:

  • Предсказуемость (состояние всегда явное).
  • Легко тестировать (чистые функции).
  • Нет утечек памяти (нет подписок вью).

Недостатки:

  • Больше шаблонного кода.
  • Сложнее для простых экранов.

Используется с RxJava/Coroutines + StateFlow.

Ответ 18+ 🔞

А, ну это та штука, где всё по полочкам разложено, как в армии, только без дедовщины. Слушай, MVI — это типа как MVVM, но который взял риталин и стал занудой-перфекционистом. Всё должно быть по струнке, однонаправленно, и никакого самодеятельности.

Чё там за кирпичики:

  • Model (Модель) — это, по сути, просто фотка состояния твоего экрана в конкретный момент. Как будто заморозили кадр. И её нельзя менять просто так, ёпта. Ты создаёшь новую. Обычно это data class, который хранит всю нужную инфу: грузится ли всё, есть ли ошибка, успешно ли залогинился пользователь.
  • View (Вьюха) — это дура-картина. Её работа — взять эту самую модель-состояние и нарисовать себя соответственно. А ещё — ловить все клики и пинки от пользователя, упаковывать их в аккуратные посылочки (интенты) и отправлять куда надо. Сама она нихуя не решает.
  • Intent (Интент) — это не тот интент, чтобы активити запускать. Это просто сигнал: «пользователь нажал кнопку логина» или «ввёл текст в поле». Чистое намерение, без подробностей бизнес-логики.

Вот тебе пример состояния, чтоб не быть голословным:

data class LoginState(
    val isLoading: Boolean = false, // Крутится ли прогресс-бар, пока мы лезем в сеть
    val error: String? = null,      // Если пришла ошибка, тут её текст. Иначе null.
    val isSuccess: Boolean = false  // Всё, залогинились, можно праздновать
)

Чем это, блядь, хорошо:

  • Предсказуемость овердохуища. У тебя в любой момент времени есть полная и явная фотка состояния экрана. Никаких скрытых флагов в десяти разных местах. Отлаживать — сказка.
  • Тестируется на ура. Поскольку логика по преобразованию интентов в новые состояния — это часто чистые функции, их можно тестировать, как боженьку. Подсунул на вход интент и старое состояние — получил на выходе новое состояние. Всё.
  • Утечек памяти можно не бздеть. Во вьюхе не должно быть подписок на какие-то там стримы, которые забыть отписаться. Вьюха просто рисует то, что ей дали.

Чем это, сука, не очень:

  • Бойлерплейта — как говна за баней. Для простого экрана с одной кнопкой придётся городить отдельные классы для состояния, интентов, редьюсеры... Иногда кажется, что ты копаешь яму лопатой, когда можно пальцем ткнуть.
  • Для простых экранов — это как из пушки по воробьям. Реально, иногда MVVM или даже чистое MVC сделают всё в разы быстрее и без этой всей бюрократии.

Короче, юзают это обычно в связке с RxJava или, что сейчас чаще, Coroutines + StateFlow/SharedFlow. Паттерн мощный, но требует дисциплины. Если в команде все понимают, что к чему — жить можно. Если нет — будет пиздец и саботаж. Выбирай с умом.