Как правильно реализовать MVP подход (паттерн)
решил перевести свой проект на паттерн MVP. Фактически основные аспекты я понял, и более менее реализовал. Но есть вопрос, над которым я ломаю голову..
Для простой работы с di, решил использовать Dagger2. А для работы с SqlLite Room.
У меня реализовано структура Activity <- -> presenter -> repository.
Repository реализует только получение и сохранение данных? А как и где данные обрабатывать? Вот например мне нужно чтобы в List который вернёт repository презенетеру, было в ручном режиме добавлено ещё несколько елементов. Как мне это реализовать?
Ответы (1 шт):
Repository реализует только получение и сохранение данных?
Обычно репозиторий занимается сохранением и загрузкой данных.
А как и где данные обрабатывать?
Вьюха(фрагмент или активити) реализует некий интерфейс через который с ней будет работать презентер, например такой:
interface NoteEditView{
fun showProgress()
fun hideProgress()
fun showError(error: String)
fun onNoteTitleUpdate(newTitle: String)
}
В саму вьюху инжектится либо сам презентер, либо интерфейс контракта для нотификации об изменениях из UI.
Например такой
interface NoteEditPresenterContract{
fun onClear()
fun viewDettached(view: NoteEditView)
fun viewAttached(view: NoteEditView)
fun onChangeTitleClicked(newTitle: String)
}
В нужные моменты жизненного цикла вьюхи мы через эти методы будем также аттачить\детачить вьюху, чтобы ничего не утекло.
В презентер инжектится вьюха(или инструмент для работы с ней который учитывает аттач\детач), а также репозиторий.
На старте презентер подписывается на нужные методы репозитория которые предоставляют ему нужные данные(например актуальный тайтл заметки), на каждое изменение в этой подписке, мы нотифицируем вьюху(если она приаттачена).
В вьюхе вешаются листенеры, например на кнопку, по нажатию в презентер улетает событе - presenter.onChangeTitleClicked(titleTextView.getText())
Далее презентер производит обработку, например принимает решение повесить прогресс бар, проверить валидность введенных символов, показ ошибки если они не валидны, или если валидны, дернуть метод репозитория для сохранения новых данных, после завершения работы репозитория, снимается прогресс бар, показывается ошибка, или успешное состояние.
После того как код обновляющий тайтл в репозитории отработает, оно само(если используются нужные инструменты вроде лайвдаты, или flow или обсерверы для бд) дернет код презентера(тк он подписан на них выше), с свеже установленным тайтлом, а презентер пнет вьюху, чтобы та обновила нужное поле.
Вот например мне нужно чтобы в List который вернёт repository презенетеру, было в ручном режиме добавлено ещё несколько елементов. Как мне это реализовать?
Лучше в “ручном” режиме ничего не делать, чем больше у тебя будет промежуточных состояний, тем больше шанс получить непонятные баги. Оптимальным для решения этой задачи использовать схему выше. Вьюха подписывается на актуальный список в презентере, презентер подписывается в репе, репа посылает актуальное презентеру если произошло изменение. Когда возникла необходимость изменить список, презентер пинает репу, и обновляет список там, а вьюха обновится сама, тк есть цепочка подписантов выше.
В целом от mvp в андроиде сейчас люди бегут, тк в нем есть ряд проблем например с аттачем\детачем вьюхи. Поэтому хорошо бы вместо данного подхода посмотреть на рекомендуемый гуглом mvvm(сильно похоже на mvp, но проще, и без этого гемороя), или модный ныне mvi.