B
B
baddev2019-05-07 11:44:18
Java
baddev, 2019-05-07 11:44:18

Android, MVP. How to determine whether to include a method in an interface or not?

Hello.
There is a popular short example of the implementation of the mvp pattern in android using the login page as an example. I'll simplify it and get to the point:
The view interface contains a method that will direct us to the user's page if the login is successful:

public interface LoginView {
    void navigateToHome();
}

Everything is clear here.
Presenter interface:
public interface LoginPresenter {
    void login();
}

In my understanding, it should be like this:
1. by clicking on the "login" button,
presenter.login() is called 2. in presenter.login() it is checked if the data is correct, then view.navigateToHome() is called
In the example that I analyze in general, everything implemented in the same way with only one detail incomprehensible to me:
1. by clicking on the "login" button, the view.validate () method for checking the correctness of the entered data is called, from which the method of the same name is called in the presenter.validate () presenter, in which all checks and if they are passed successfully, then login () is already called.
My question is, what is the reason that the validate () methods are not registered in the view and presenter interfaces? How to understand whether it is necessary to register a method in an interface or not? Thank you all in advance.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Zagaevsky, 2019-05-07
@baddev

IMHO, this is a terrible mess.
View must have methods for displaying data only. navigateToHome is not one of them, it should be a separate Router object, which is not in the MVP.
View should not have a link to Presenter and pull some methods from it.
There should be no business logic in the View.
The Presenter must have a reference to the View.
Events (rx observable or callbacks, for example) that the Presenter subscribes to should stick out from the View.
The Presenter must have two methods to bind it to the View: bind(View), unbind(View).
Fragment or Activity must not be a View, Presenter or Model. They are the glue, the system mechanisms for linking and maintaining the stack of screens. They somehow create or receive instances of View and Presenter through DI, and bind them using bind / unbind.
Thus, there will be no validate methods in any interface, and in any implementation (unless they are private implementation methods, of course).
Simplified like this

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);
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question