Ответ
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. Паттерн мощный, но требует дисциплины. Если в команде все понимают, что к чему — жить можно. Если нет — будет пиздец и саботаж. Выбирай с умом.