При повороте экрана Presenter в MVP умирает вместе с Activity. Это приводит к потере состояния и перезагрузке данных. Разработчики тратят до 40% времени тестирования на отладку таких сценариев. Наша команда за 7 лет настроила MVP на более чем 50 проектах — от финтеха до корпоративных порталов. Расскажем, как избежать типичных ошибок и сделать архитектуру тестируемой.
MVP (Model-View-Presenter) остаётся оптимальным выбором для legacy-проектов на Java. Переход на Kotlin + ViewModel не всегда оправдан: рефакторинг может занять 2–3 недели и стоить дорого. MVP позволяет сохранить инвестиции в код, сократив объём Activity на 50–60% и время на тестирование до 40%. Например, в одном проекте с 30 экранами мы уменьшили количество багов на 30% за счёт изоляции логики в Presenter.
Почему MVP всё ещё актуален?
MVP выбирают, когда:
- Более 70% кода написано на Java, и полный рефакторинг экономически нецелесообразен.
- Команда привыкла к MVP и не хочет менять стабильный паттерн.
- Требуется максимальная тестируемость: Presenter легко покрыть юнит-тестами без Android-зависимостей.
- Проект уже использует Dagger 2 или Hilt.
Согласно Model–view–presenter, MVP разделяет ответственность между тремя компонентами: Model (данные и бизнес-логика), View (интерфейс, реализуемый Activity/Fragment), Presenter (логика представления). Это классическое разделение остаётся эффективным.
MVP — это архитектурный паттерн, который отделяет пользовательский интерфейс от бизнес-логики. — Martin Fowler
Как устроена MVP-архитектура?
Три участника: Model, View, Presenter. Контракты задаются через интерфейсы.
public interface ProfileContract { interface View { void showProfile(UserProfile profile); void showError(String message); void showLoading(boolean show); } interface Presenter { void loadProfile(String userId); void onDestroy(); } } Реализация Presenter использует RxJava для асинхронности:
public class ProfilePresenter implements ProfileContract.Presenter { private final ProfileContract.View view; private final UserRepository repository; private CompositeDisposable disposables = new CompositeDisposable(); public ProfilePresenter(ProfileContract.View view, UserRepository repository) { this.view = view; this.repository = repository; } @Override public void loadProfile(String userId) { view.showLoading(true); disposables.add( repository.getProfile(userId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( profile -> { view.showLoading(false); view.showProfile(profile); }, error -> { view.showLoading(false); view.showError(error.getMessage()); } ) ); } @Override public void onDestroy() { disposables.clear(); } } Activity реализует ProfileContract.View, создаёт Presenter в onCreate, вызывает presenter.onDestroy() в onDestroy.
Как решить проблему поворота экрана?
Это главный недостаток MVP по сравнению с MVVM: Presenter не переживает пересоздание Activity. Решения:
- Хранить Presenter через
retain Fragment(устарело). - Использовать
ViewModelStore(ирония — используем ViewModel как контейнер для Presenter). - Принять утрату состояния и перезагружать данные.
В проектах, где MVP устоялся, часто выбирают второй путь: RetainedPresenterFragment без UI, который хранит Presenter в setRetainInstance(true). Работает, но выглядит как костыль. Мы рекомендуем использовать ViewModel как хост для Presenter — это даёт чистую интеграцию с Jetpack.
Сравнение MVP и MVVM
| Критерий | MVP | MVVM (ViewModel) |
|---|---|---|
| Тестируемость | Отличная: Presenter без Android-зависимостей | Хорошая, но требует DI для Repository |
| Управление состоянием при повороте | Требует дополнительных усилий | Встроено через ViewModel |
| Сложность для простых экранов | Ниже | Выше из-за LiveData/StateFlow |
| Поддержка Kotlin | Работает, но теряются преимущества | Естественная интеграция |
| Порог входа для команды | Меньше, если Java-опыт | Больше, требуется знание Jetpack |
MVVM в 3 раза упрощает управление состоянием при повороте экрана, но MVP в 2 раза быстрее в тестировании. Выбор зависит от контекста: для нового Kotlin-проекта — MVVM, для legacy Java — MVP.
Когда стоит выбрать MVP вместо MVVM?
Если ваш проект на Java с использованием Dagger 2, переход на MVVM потребует замены DI на Hilt или Koin и переписывания всех ViewModel. Это может стоить дороже, чем оставить MVP и добавить ViewModel только для управления состоянием Presenter. MVP дешевле в поддержке, если команда не готова учить Jetpack.
Процесс внедрения MVP
- Анализ текущей архитектуры — оценка объёма кода и точек входа.
- Проектирование контрактов — интерфейсы View и Presenter для каждого экрана.
- Рефакторинг экранов — вынос логики из Activity/Fragment в Presenter.
- Настройка DI — интеграция Dagger 2 для внедрения Repository и других зависимостей.
- Написание тестов — юнит-тесты Presenter с Mockito.
- Code review и деплой — проверка кода и поставка в production.
Этот процесс занимает 2–3 дня для настройки с нуля и 1–2 недели для рефакторинга существующего проекта. Мы бесплатно оценим ваш проект и предложим план. Для получения консультации свяжитесь с нами.
Что входит в настройку MVP под ключ?
- Создание базовых классов
BasePresenterиBaseViewс управлением жизненным циклом. - Генерация контрактов для всех экранов.
- Подключение Dagger 2 с примерами модулей.
- Написание тестов Presenter через JUnit + Mockito без Android-зависимостей.
- Документация по архитектуре и рекомендации для команды.
- Консультация и код-ревью на этапе внедрения.
Типичная структура контракта
Контракт включает интерфейсы View и Presenter. View определяет методы отображения данных и состояний, Presenter — методы загрузки и обработки. Это обеспечивает строгую типизацию и упрощает тестирование.Частые ошибки при внедрении MVP
Хранение Presenter как статической переменной приводит к утечкам памяти. Используйте ViewModel или retain Fragment. Вместо instanceof в View применяйте интерфейс контракта. Отсутствие методов onPause/onResume в Presenter исправляется добавлением управления подписками через CompositeDisposable. Передача Activity в Presenter нарушает независимость — инжектите только View через контракт. Избегая этих ошибок, вы получите чистую, тестируемую архитектуру, которая экономит до 40% времени на тестирование.
Закажите настройку MVP в вашем проекте — получите консультацию инженера с 7-летним опытом. Мы гарантируем сокращение кода на 50% и улучшение тестируемости.







