Model View Presenter (MVP) no Android com um projeto de demonstração simples.
Model-view-presenter (MVP) é uma derivação do padrão arquitetônico model-view-controller (MVC) que é usado principalmente para construir interfaces de usuário. No MVP, o apresentador assume a funcionalidade de “intermediário”. No MVP, toda a lógica de apresentação é enviada ao apresentador. O MVP defende a separação da lógica de negócios e persistência da atividade e do fragmento
Conteudo
Diferenças entre MVC e MVP
- Os controladores são baseados em comportamento e podem compartilhar várias visualizações.
- View pode se comunicar diretamente com o modelo
- Veja mais separado do modelo. O Apresentador é o mediador entre o Modelo e a Visualização.
- Mais fácil de criar testes de unidade
- Geralmente, há um mapeamento um para um entre Visualização e Apresentador, com a possibilidade de usar vários Apresentadores para Visualizações complexas
- Ouça a ação do usuário e as atualizações do modelo
- Atualiza o modelo e a visualização também
Model
Em um aplicativo com uma boa arquitetura em camadas, esse modelo seria apenas a porta de entrada para a camada de domínio ou lógica de negócios. Veja-o como o provedor dos dados que queremos exibir na visualização. As responsabilidades do modelo incluem o uso de APIs, armazenamento de dados em cache, gerenciamento de bancos de dados e assim por diante.
View
A Visualização, geralmente implementada por uma Atividade, conterá uma referência ao apresentador. A única coisa que a visualização fará é chamar um método do Presenter sempre que houver uma ação de interface.
Presenter
O Apresentador é responsável por atuar como intermediário entre a Visualização e o Modelo. Ele recupera dados do Modelo e os retorna formatados para a Visualização. Mas, ao contrário do MVC típico, ele também decide o que acontece quando você interage com o View.
Fluxo de Trabalho Simples do Projeto
Aqui, tento ilustrar o básico do padrão MVP com um projeto android de demonstração simples que está disponível no GITHUB. O projeto possui apenas uma tela que possui o nome de usuário e e-mail EditText e uma TextView. Quando o usuário tenta inserir nome de usuário ou e-mail, os dados de entrada serão mostrados na parte superior da tela em TextView.
MainActivityPresenter.java
Aqui, MainActivityPresenter.java funciona como um intermediário entre a visualização e o modelo. Ele escuta a ação do usuário, atualiza o modelo de dados e a visualização.
public class MainActivityPresenter { private User user; private View view; public MainActivityPresenter(View view) { this.user = new User(); this.view = view; } public void updateFullName(String fullName){ user.setFullName(fullName); view.updateUserInfoTextView(user.toString()); } public void updateEmail(String email){ user.setEmail(email); view.updateUserInfoTextView(user.toString()); } public interface View{ void updateUserInfoTextView(String info); void showProgressBar(); void hideProgressBar(); } }
User.java
public class User { private String fullName = "", email = ""; public User() { } public User(String fullName, String email) { this.fullName = fullName; this.email = email; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Email : " + email + "\nFullName : " + fullName; } }
MainActivity.java
Em primeiro lugar, esta atividade implementa a Interface MainActivityPresenter.View, por meio da qual o método substituído será chamado. Em segundo lugar, temos que criar o objeto MainActivityPresenter com visão como um construtor. Usamos este objeto apresentador para ouvir a entrada do usuário e atualizar os dados, bem como visualizar.
public class MainActivity extends AppCompatActivity implements MainActivityPresenter.View { private MainActivityPresenter presenter; private TextView myTextView; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); presenter = new MainActivityPresenter(this); myTextView = findViewById(R.id.myTextView); EditText userName = findViewById(R.id.username); EditText email = findViewById(R.id.email); initProgressBar(); userName.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { presenter.updateFullName(s.toString()); } @Override public void afterTextChanged(Editable s) { hideProgressBar(); } }); email.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { presenter.updateEmail(s.toString()); } @Override public void afterTextChanged(Editable s) { hideProgressBar(); } }); } private void initProgressBar() { progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleSmall); progressBar.setIndeterminate(true); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(Resources.getSystem().getDisplayMetrics().widthPixels, 250); params.addRule(RelativeLayout.CENTER_IN_PARENT); this.addContentView(progressBar, params); showProgressBar(); } @Override public void updateUserInfoTextView(String info) { myTextView.setText(info); } @Override public void showProgressBar() { progressBar.setVisibility(View.VISIBLE); } @Override public void hideProgressBar() { progressBar.setVisibility(View.INVISIBLE); } }
Resultado: