Best practices for MVP pattern on Android

androidmvp

my team has had great success introducing MVP and the associated unit tests that go with the presenter.
We are wondering how granular we should make the interaction between the View and the Presenter.

For example, we have a screen that displays a loading icon and then makes a request for some data. When the call returns, we remove the loading icon and display the data.

In this scenario we could make the View really dumb and delegate to the Presenter on start up and be told to display the loading icon. Then the presenter would make the request and when that returns, tell the View to remove the loading icon and then make another view call with the data to be displayed.

Another way we could do this is to have the activity display the loading icon then call the presenter. The presenter would make the call, receive a callback when it returns and then call the view with the results. Its up to the activity to know to remove the loading icon and then display the data.

In the first instance the view is told explicitly everything it should do and the second only delegates 'business logic' to the presenter.

What do people think is the better approach?

Best Answer

Here is an example of what the interface between the View and Presenter could be, from this article

interface MessageView {
  // View methods should be directives, as the View is just executing orders from the 
  // Presenter.

  // Methods for updating the view
  void setMessageBody(String body);
  void setAuthorName(String name);
  void showTranslationButton(boolean shouldShow);

  // Navigation methods
  void goToUserProfile(User user);
}

interface MessagePresenter {
  // Presenter methods should mostly be callbacks, as the View is reporting events for the
  // Presenter to evaluate

  // Lifecycle events methods
  void onStart();

  // Input events methods
  void onAuthorClicked();
  void onThreeFingersSwipe();
}

Here are a couple of interesting points to notice about this interface:

  • The methods to update the view should be simple and targeted on a single element. This is better than having a single setMessage(Message message) method that will update everything, because formatting what should be displayed should be the responsibility of the Presenter. For example, you might want to start displaying “You” instead of the user name if the current user is the author of the message, and this is part of your business logic.
  • Lifecycle events methods on the Presenter are simple and don’t have to map the (overly complicated) Android lifecycle ones. You don’t have to implement any of them, but you can implement as many as you want if the Presenter needs to take specific actions.
  • Input events methods on the Presenter are kept at a high level. If for example you’re trying to detect a complex gesture, like the 3 fingers swipe example, all the gesture detection should be done in the View. You can see that there are MessagePresenter.onAuthorClicked() and MessageView.goToAuthorProfile() methods. The implementation of the View will probably have a click listener that calls this Presenter method that will call goToAuthorProfile(). Should you skip all this and just directly go to the author profile from the click listener? No! The decision of going to that profile when the author name is clicked is part of your business logic, and belongs in the Presenter.