Для реализации MVP использую Moxy. Сегодня в первый раз использую данную либу, может уже из коробки есть решения возникших вопросов, но я не знаю о них. В целом вопрос больше в плане как это сделать не нарушая канонов MVP...
Да, я знаю что в Moxy сохраняется ViewState при обращении из презентера getViewState().showData(data);
Есть фрагмент, в котором запись редактируется(если она ранее была создана) или создается новая запись. Если фрагмент открываем в режиме редактирования то в Arguments передаю ID записи который нужно редактировать.
На самом деле у меня возникло 3 вопроса по этому кэйсу:
Когда презентер получает данные из репозитория(например, из сети), он должен его кэшировать в своем private поле? например, для последующей модификации при изменении из вьюшки (например, меняем текст в EditText)..
В случае если мы заходим в режиме редактирования, презентер подгружает информацию о редактируемой записе(например, MyData) и отправляет вьюшке для отображения. Теперь, пользователь редактирует запись(меняет текст в EditText, добавляет фото) - что должно происходить в этот момент? При любых изменениях мы должны эти изменения отправлять в презентер? Вот так:
presenter.addImage(imagePath);
presenter.editTitle(newTitleText);
и что дальше презентер с этим должен делать? Модифицировать сохраненное в private поле из п.1 данные с помощью полученных в методах addImage и editTitle данными?
Какая будет логика в пунктах выше, если зашли в режиме создания новой записи?
Пункт №2, №3 интересны из-за пересоздания View при смене конфигурации.. Где же сохранять "сырые" данные?
Интересует как вы решаете такие кейсы! Как это сделать по умному не нарушая принципы паттерна MVP?
оффтоп:
И еще, где-то читал, что, код типа этого: presenter.addImage(imagePath);
неправильный, view не должно говорить презентуру что делать, а тут я говорю добавь фото. Или я просто неправильно понял ту мысль которую излагали?!
Если все же я правильно понял, то я в ступоре..) Например, во вьюшке кликнул кнопку "добавить фото", презентер узнал об этом и отправил вьюшке команду "открой окно выбора", в этом окне я выбрал фото(из галереи), далее в onActivityResult получаю путь выбранной картинки, и по сути я должен с этой картинкой что то делать, или выполнить presenter.addImage(imagePath) или сообщить презентуру что, что то произошло и презентер должен это как-то обработать(а в этот момент пока я сообщаю презентеру и презентер как то начинает это обрабатывать где будет храниться картинка которая пришла в onActivityResult ? где то во вью? тогда получается вьюшка уже занимается не только вопросами UI). А как вообще на практике это решается? какой подход считается общепринятым? - вопрос для всех кто прочитает))
Лучше кэшировать данные в репозитории, потому что репозиторий ответственен за управлением источниками данных(сети, базы, кеша). Здесь много разных подходов, я написал тот, который предлагает гугл.
Контракт (если хотите, можете оформить в виде интерфейса презентера) может быть такой:
public interface INotePresenter {
void saveClicked();
void imageChosen(File file);
void editTitleClicked(String title);
}
Методы называются так, потому что как вы сами написали вьюха не должна говорить презентеру что делать, поэтому в названии метода сообщаем только то, что произошло какое-то событие.
Презентер можете создать через метод мокси
@ProvidePresenter
NotePresenter provideNotePresenter() {
Bundle bundle = this.getArguments();
int id = Objects.requireNonNull(bundle).getInt(NOTE_ID, 0);
if( id == 0){
return new NotePresenter();
}else{
return new NotePresenter(id)
}
}
В пустом конструкторе вы ничего не делаете. В конструкторе с айдишником делаете запрос в ваш репозиторий и устанавливаете getViewState().showData(data);
Остальные методы презентера проксируете(оборачиваете) в репозиторий. Можно только названия поменять на addImage(file)
, addTitle(title)
Уже в репозитории при вызове метода getData(id)
вы кэшируете ваш объект mData, как глобальную переменную private MyData mData = new MyData();
.
При вызове imageChosen(file)
добавляете путь файла в кеше(объекте mData).
При вызове editTitleClicked(String title)
обновляете тайтл в mData .
Метод saveClicked()
можно сделать примерно таким:
private void saveClicked(){
if(mData.getId() == 0){
mDb.insert(mData);
}else{
mDb.update(mData);
}
}
Если у вашего айтема есть айдишник, то значит он был взят из бд и айтем надо обновить, если нет то значит это читсый кеш нового айтема и его надо вставить.
Создали пустой объект, отобразили на вьюхе, его отредактировали и сохранили, вы сохранили в репозитории, который вернул новый объект в итоге, например с присвоенным ID.
Original
, Proposed
,Current
. Так вот, когда происходит какая-то модификация значение переносится в поле Proposed
и Current. Когда значения комитятся, то все 3 состояния равны. Т.е как вариант, вы можете в свою модель добавить хранение промежуточного состояния.Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всё отработало и показало 1 - Sts, то есть исключило дубликатОбъясните почему везде пишется что нужно переопределить hashCode()иequals() чтобы это заработало...
у меня есть функция написаная на C++(JNI) которая получает как параметр jobject (это по сути мой List) и заполняет его данными
Вот пример из книги которую читаю и совершенно не понимаю вот этого (fs&1 > 0) и аналогичных далее выражений