Arquitetura MVP no desenvolvimento de aplicativos Android

Bom, antes de nos aprofundarmos no mundo do MVP, precisamos entender/relembrar alguns princípios básicos sobre arquitetura. Vamos lá!?

Porque é tão importante definir uma arquitetura?

Definindo uma arquitetura, tornamos nosso app íntegro, fácil de se dar eventuais manutenções, fácil de ser gerenciado, testável, além de podermos reutilizar nosso código.

O que é o MVP e porque adotá-lo?

Esquema da arquitetura MVP

O MVP (Model-View-Presenter) é um tipo de arquitetura de software, conhecido pelas abstrações das camadas que ele propõe, separando lógica de dados com lógicas de visualização. É uma arquitetura que facilita os testes unitários e testes integrados, além dos benefícios citados no tópico acima.

Agora vamos entender como implementar o MVP!

Antes de tudo, precisamos além de planejar o que queremos desenvolver, devemos entender os princípios de uma implantação correta do MVP.

Model: Assim como já citado são todas as classes modelo, factories, ou seja, são classes POJO(Plain Old Java Object). Até aqui não teremos mudança em relação a arquitetura.

View: Nossas activities, fragments, componentes e todos responsáveis por exibir dados na tela, além de capturar ações do usuário na UI (User Interface).

Presenter: Classe responsável por ministrar todas lógica de negócio e apresentação, mediadora do fluxo de dados entre View e Model. É criado um contrato para deixar as responsabilidades totalmente definidas, onde faz o papel de mediador entre Presenter e View. É uma simples interface, responsável por obter um melhor desacoplamento, ou seja, o Presenter não necessita de uma instância real da View e vice-versa, assim o contrato faz esse “meio de campo”.

Vamos ver código e compreendê-lo agora?

Bom, irei criar um app bem simples, que calculará dois números inputados pelo usuário.

Começando em “camadas”, vamos ao Contrato:

package app.vanderlei.com.mediumapp;

public interface MainPresenterContract {

interface Presenter {
void calculate(int numberOne, int numberTwo);

}

interface View {
void showResult(Model model);
}

}

Como já dito, nosso contrato é uma interface, que em sua implementação possui duas inner interfaces, respectivamente Presenter e View.

Na interface Presenter, deve conter todos os métodos que serão necessários ser usados no Presenter, lembrando que aqui ficam os métodos que ministram as lógicas de dados.

Já na interface View, deve conter todos os métodos que serão necessários ser usados na View (no nosso caso, a Activity), como por exemplo, exibir algo na tela.

Na implementação perfeccionista do MVP, é ideal que, todos os métodos do contrato sejam do tipo void, como uma precaução para não ocorra acoplamento do Presenter com a View. Ressaltando que o Presenter não deve saber o que tem na View que possui sua referência, e muito menos quem é essa View.

Presenter:

package app.vanderlei.com.mediumapp;

public class MainPresenter implements MainPresenterContract.Presenter{

MainPresenterContract.View mView;

public MainPresenter(MainPresenterContract.View view) {
mView = view;
}

@Override
public void calculate(int numberOne, int numberTwo) {
if (mView != null) {
int result = numberOne + numberTwo;
Model model = new Model(numberOne, numberTwo, result);
mView.showResult(model);
}
}
}

A classe Presenter, deve suportar todas as lógicas referentes ao fluxo do model até a exibição na view. Sendo assim, ele deve implementar a interface Presenter, do nosso contrato.

Após isso, precisaremos de uma referência para conseguirmos mandar esse fluxo para a view, teremos uma instância da interface View do contrato, dessa forma, não criamos acoplamento e apenas serão chamados metódos da view que estiverem no contrato.

Devemos sempre lembrar do básico, a checagem de nulo! Pois pode acontecer de alguma exception ser disparada, nossa view ser destruida e o presenter continuar em execução.

Activity:

package app.vanderlei.com.mediumapp;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements MainPresenterContract.View {

EditText mNumberOne, mNumberTwo;
Button mButton;
TextView mTextView;
MainPresenter mPresenter;

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

mPresenter = new MainPresenter(this);

mNumberOne = (EditText) findViewById(R.id.et1);
mNumberTwo = (EditText) findViewById(R.id.et2);
mButton = (Button) findViewById(R.id.button);
mTextView = (TextView) findViewById(R.id.tv1);

mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPresenter != null) {
mPresenter.calculate(Integer.parseInt(mNumberOne.getText().toString()),
Integer.parseInt(mNumberTwo.getText().toString()));
}
}
});

}

@Override
public void showResult(Model model) {
mTextView.setText(model.getResult());
}
}

Na nossa view(no nosso caso, a activity), devemos nos preocupar sempre em não estar alocando lógicas de negócios, o ideal é sempre tentar manter a view da forma mais “burra” possível, apenas com a função de exibir e setar coisas esperadas pelo Presenter.

Models e XML:

Aqui não teremos mudança por conta da arquitetura, prosseguiremos com uma classe POJO e um XML básico com poucos componentes.

Like what you read? Give Vanderlei Lopes a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.