Sobes.tech
Junior

Tell me more about the MVP (Model-View-Presenter) pattern.

sobes.tech AI

Answer from AI

MVP divides the application into three components:

  • Model: the data and business logic layer. It is independent of the presentation (View).
  • View: the user interface layer. It displays data from the Presenter and sends user actions to it. It does not contain business logic.
  • Presenter: the intermediary between Model and View. It contains presentation logic, receives data from the Model, formats it for the View, and handles user actions.

Interaction:

  1. The View informs the Presenter about a user action (e.g., button click).
  2. The Presenter processes the action, possibly requesting or modifying data in the Model.
  3. The Model performs the operation and returns the result to the Presenter.
  4. The Presenter updates the View, passing the necessary data for display.

Advantages:

  • Improved separation of responsibilities.
  • Increased testability (the Presenter can be tested separately from the View).
  • Simplified maintenance and extension of the code.

Disadvantages:

  • Increased number of classes and interfaces.
  • More complex initial setup compared to MVC.

Example:

// View interface
interface LoginView {
    void showProgress();
    void hideProgress();
    void setUsernameError(String error);
    void setPasswordError(String error);
    void navigateToHome();
}

// Presenter interface
interface LoginPresenter {
    void validateCredentials(String username, String password);
    void onDestroy(); // For resource cleanup
}

// Presenter class
class LoginPresenterImpl implements LoginPresenter {

    private LoginView loginView;
    // Reference to Model (e.g., UserRepository)

    public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
    }

    @Override
    public void validateCredentials(String username, String password) {
        loginView.showProgress();
        // Validation logic and Model interaction
        if (username.isEmpty()) {
            loginView.setUsernameError("Username cannot be empty");
            loginView.hideProgress();
            return;
        }
        // Continue for password and validation logic
        
        // If validation is successful and Model returns success:
        // loginView.navigateToHome();
    }

    @Override
    public void onDestroy() {
        loginView = null; // Prevent memory leaks
    }
}

// Usage example in View (e.g., in Activity)
public class LoginActivity extends AppCompatActivity implements LoginView {

    private LoginPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        presenter = new LoginPresenterImpl(this);

        findViewById(R.id.login_button).setOnClickListener(v -> {
            String username = ((EditText) findViewById(R.id.username)).getText().toString();
            String password = ((EditText) findViewById(R.id.password)).getText().toString();
            presenter.validateCredentials(username, password);
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.onDestroy();
    }

    @Override
    public void showProgress() {
        // Show progress indicator
    }

    @Override
    public void hideProgress() {
        // Hide progress indicator
    }

    @Override
    public void setUsernameError(String error) {
        // Display username input error
    }

    @Override
    public void setPasswordError(String error) {
        // Display password input error
    }

    @Override
    public void navigateToHome() {
        // Navigate to the next screen
    }
}