Как реализовывать связи между Model, View и Presenter + Room?
Не могу понять как реализовать связь в MVP + Room.
На примере приложения "Заметки":
Я создал БД с использованием Room.
@Database(entities = {Note.class}, version = 1, exportSchema = false)
public abstract class NotesDatabase extends RoomDatabase {
private static NotesDatabase database;
private static final String DB_NAME = "notes.db";
private static final Object LOCK = new Object();
public static NotesDatabase getInstance(Context context) {
synchronized (LOCK){
if (database == null) {
database = Room.databaseBuilder(context, NotesDatabase.class, DB_NAME)
.build();
}
}
return database;
}
public abstract NotesDao notesDao();
}
Создал Model, в которой находятся запросы к БД
public class MainModel{
private static NotesDatabase database;
private LiveData<List<Note>> notes;
public MainModel(Application application) {
database = NotesDatabase.getInstance(application);
notes = database.notesDao().getAllNotes();
}
public LiveData<List<Note>> getNotes() {
return notes;
}
public void deleteAllNote() {
new DeleteNotesTask().execute();
}
public void insertNote(Note note) {
new InsertTask().execute(note);
}
public void deleteNote(Note note){
new DeleteTask().execute(note);
}
public Note getNoteById(int id) {
try {
return new GetNoteTask().execute(id).get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
return null;
}
public void updateNote(Note note) {
new UpdateTask().execute(note);
}
private static class DeleteTask extends AsyncTask<Note, Void, Void> {
@Override
protected Void doInBackground(Note... notes) {
if (notes != null && notes.length > 0) {
database.notesDao().deleteNote(notes[0]);
}
return null;
}
}
private static class DeleteNotesTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
database.notesDao().deleteAllNote();
return null;
}
}
private static class InsertTask extends AsyncTask<Note, Void, Void> {
@Override
protected Void doInBackground(Note... notes) {
if (notes != null && notes.length > 0) {
database.notesDao().insertNote(notes[0]);
}
return null;
}
}
private static class GetNoteTask extends AsyncTask<Integer, Void, Note> {
@Override
protected Note doInBackground(Integer... integers) {
if (integers != null && integers.length > 0) {
return database.notesDao().getNoteById(integers[0]);
}
return null;
}
}
private static class UpdateTask extends AsyncTask<Note, Void, Void> {
@Override
protected Void doInBackground(Note... notes) {
if (notes != null && notes.length > 0) {
database.notesDao().updateNote(notes[0]);
}
return null;
}
}
}
И дальше совсем не понятно как это все связать между собой и к тому же со View and Presenter.
Пытался написать Presenter, но абсолютно нет понимания как это сделать правильно. Пример Presenter:
public class MainPresenter {
private MainModel model;
private NotesAdapter adapter;
private List<Note> notes = new ArrayList<>();
public void getData() {
LiveData<List<Note>> notesFromDb = model.getNotes();
notesFromDb.observe([что писать в качестве owner?], new Observer<List<Note>>() {
@Override
public void onChanged(List<Note> notesFromLiveData) {
notes.clear();
notes.addAll(notesFromLiveData);
adapter.notifyDataSetChanged();
}
});
}
}
Помогите, пожалуйста, разобраться с вопросом.
Ответы (1 шт):
Допустим у нас есть MVP (Model View Presenter). Классическая схема выглядит примерно так:
Давайте разберем, что здесь и как работает. У нас есть 3 основные сущности:
View - это некий UI (чаще всего это ваш
FragmentилиActivity) единственной задачей которого является рисовать интерфейс для пользователя и сообщать о действиях пользователяPresenter-у. View должна быть тупой до безобразия, в ней не должно быть никакой логики, она не должна уметь сама что-то считать или получать какие-либо данные. Только рисовать и сообщать о действиях пользователяPresenter-у.Presenter - это собственно сущность которая отвечает за логику. Именно здесь происходят какие-то расчеты, именно здесь решается что показать пользователю, именно здесь решается как отреагировать на действия пользователя.
Model - это любая сущность которая отвечает за данные. Часто это Repository, но это может быть и ваша база данных и
Retrofit(или любая другая сущность отвечающая за походы в сеть). Задача Model-и предоставлять данные. Только Model знает откуда они приходят.
Нужно понимать, что View имеет в себе ссылку на Presenter и понятия не имеет о существовании Model-и. Presenter знает о Model-и и имеет ссылку на интерфейс View. Model вообще не знает ни о ком и ни от кого не зависит. Она не зависит ни от чего. В данной схеме это самый верхний уровень, в то время как View - самый нижний уровень, который зависит от других уровней.
Теперь поговорим о взаимодействии этих сущностей:
Допустим у нас есть экран авторизации. На этом экране есть 2 поля ввода (логин и пароль) и кнопка "авторизоваться". Пользователь вошел в приложение, ввел свой логин и пароль и нажал кнопку.
View считала данные из двух полей ввода и вызвала у Presenter-a метод
presenter.login(login, password);Presenter проверил данные на валидность (например, чтоб в логине не было символов) и обратился к модели
model.auth(login, password);Метод к примеру возвращаетcallbackс ответом (onResponse(),onFailure())Model сходила на сервер, проверила там данные и вернула ответ который и прилетит в
callbackкоторый вы реализуете в Presenter-e, например все ок и мы упадем вonResponse()В Presenter-e в
onResponse()мы получаем ответ с данными о пользователе и хотим открыть второй экран. Здесь мы обращаемся к интерфейсу Viewview.openNextScreen(userData)Наша View реализует интерфейс с которым работает Presenter и при вызове метода
openNextScreen()в Presenter-e она вызываетstartActivity(...).
Это простой пример на пальцах что такое MVP и как это все между собой взаимодействует. Есть очень много разных реализаций, но сводится все примерно к такому флоу.
Накину несколько ссылок для более подробного изучения:
Мой старенький MVP шаблонный проект. Здесь нет Model-и но есть взаимодействие Presenter-a с View, а Model прикрутить не сложно.
Android MVP пример для начинающих. Без библиотек и интерфейсов.
MVP в Android приложении: Часть 1; Часть 2; Часть 3. Здесь отличное и обширное описание MVP в андроиде.
