Adnroid, MVP. Как определять, включать метод в интерфейс или нет?

Здравствуйте.
Есть популярный короткий пример реализации паттерна mvp в android на примере страницы логина. Упрощу его и перейду к сути вопроса:

Интерфейс вьюхи содержит метод, который нас направит на страницу пользователя, если логин будет удачным:
public interface LoginView {
    void navigateToHome();
}

Тут все понятно.

Интерфейс презентера:
public interface LoginPresenter {
    void login();
}


В моем понимании должно быть так:
1. по нажатии на кнопку "логин" вызыватеся presenter.login()
2. в presenter.login() проверяется, если данные корректные, то вызывается view.navigateToHome()

В примере который разбираю в целом все реализовано так же лишь с одной непонятной мне деталью:
1. по нажатии на кнопку "логин" вызывается метод проверки корректности введенных данных view.validate(), из которого происходит вызов одноименного метода в презентере presenter.validate(), в котором и осуществляются все проверки и если они пройдены успешно, то вызывается уже login()

Мой вопрос в том, чем обусловлено то, что методы validate() не прописаны в интерфейсах view и presenter? Как понимать, нужно ли прописывать метод в интерфейсе или нет? Заранее всем спасибо.
  • Вопрос задан
  • 258 просмотров
Решения вопроса 1
zagayevskiy
@zagayevskiy Куратор тега Java
Android developer at Yandex
Имхо, всё это жуткий отстой.
View должно иметь методы только по показу данных. navigateToHome к ним не относится, это должен быть отдельный объект Router, которого нет в MVP.
View не должно иметь ссылку на Presenter и дергать из него какие-то методы.
Во View не должно быть бизнес-логики.
Presenter должен иметь ссылку на View.
Из View должны торчать наружу события(rx observable или коллбеки, например), на которые подписывается Presenter.
У Presenter'a должно быть два метода для связывания его с View: bind(View), unbind(View).
Fragment или Activity не должны быть ни View, ни Presenter'ом, ни Model. Они - клей, системные механизмы для связывания и поддержания стека экранов. Они каким-либо создают или получают через DI инстансы View и Presenter, и cвязывают их при помощи bind/unbind.

Таким образом, методов validate не будет ни в одном интерфейсе, и ни в одной реализации(если только это не приватные методы реализации, конечно).

Упрощенно как-то так
interface LoginView {
    @NonNull Observable<String> names();
    @NonNull Observable<String> passwords();

    void showError(@NonNull String error);
}

interface LoginPresenter {
    void bind(@NonNull LoginView view);
    void unbind(@NonNull LoginView view);
}

interface Router {
     void navigateToHome();
}

class LoginPresenterImpl implements LoginPresenter {

     @Inject
     LoginPresenterImpl(router: Router){...}

    private CompositeDisposable disposables = new CompositeDisposable();
    @Override
    void bind(@NonNull LoginView view) {
        disposable.add(
            Observable.combineLatest(view.names(), view.passwords(), (name, password) -> validate(name, password))
                  .doOnNext(validated -> {if(!validated) view.showError("invalid login")}
                  .filter(it -> it)
                  .subscribe(it -> router.navigateToHome())
        );
    }

    @Override
    void unbind(@NonNull LoginView view) {
        disposables.clear();
    }
}

class Fragment {
    @Injecte
    LoginPresenter presenter;
    @Inject 
    LoginView view;
    
     onViewCreated() {
       presenter.bind(view) 
    }

   onDestroyView() {
       presenter.unbind(view);
    }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы