Aula 4 - Model e Arquiteturas no Android

android, tutorial,

Aula 4 - Model e Arquiteturas no Android

Camila L. Oliveira Camila L. Oliveira Nov 14, 2021 · 5 mins de leitura
Aula 4 - Model e Arquiteturas no Android
Compartilhe

O Model é responsável pelo gerenciamento de dados de uma aplicação. Seu código lembra a criação de uma tabela de banco de dados, onde temos os atributos e o tipo de valores a ser preenchidos para eles. Exemplo:


Usuário| —| id Int | nome String| —

Sua aplicação em um projeto de Android varia de arquitetura para arquitetura. Mas o que são elas?

Arquiteturas

Arquiteturas são formas as quais tratamos a conexão de uma Activity ou Fragment com os componentes, tais como o Modelo juntamente ao Controller, Presenter ou View Model (o mais utilizado e recomendado pelo guia de desenvolvimento Android). Vamos ver cada um deles:

  • MVC: Esta abordagem separa sua aplicação em um nível macro com 3 conjuntos de responsabilidades, ilustradas na imagem abaixo:

MVC Example

Model View Controller
Irá conter Data (Dados) + State (Estado) + Business Logic (Lógica de Negócio), de forma não técnica. Podemos usar como exemplo lógica comercial, acesso a dados e regra de negócios, que não está ligado a View ou Controller e com isto se torna muito reutilizável. Irá representar o Model, sendo a UI (Interface para Usuário) e faz a comunicação com a Controller sempre que ocorre uma interação do usuário. O ideal é que quanto menos eles souberem do que deve ser feito com a interação, mais flexíveis serão para mudar. É o responsável pelo que acontece no aplicativo. Quando a View diz para o Controller que um usuário clicou em um botão, ele decide como interagir. Se ocorrer modificação de dados no Model, o Controller pode decidir atualizar o estado de exibição, quase sempre representado por uma activity ou fragment. Há quem diga que ele é o coordenador entre a View e o Model.
  • Vantagens: O Model pode ser facilmente testado, porque não está vinculado a nada e a View não tem muito para testar em um nível de teste unitário.
  • Desvantagens:
    • Testabilidade: O controlador está tão ligado às APIs do Android que é difícil testar a unidade.
    • Modularidade e flexibilidade: Os Controllers estão bem acoplados às Views, sendo até mesmo uma extensão da View. Se mudarmos a View, devemos voltar e mudar o Controller.
    • Manutenção: Ao longo do tempo, particularmente em aplicações com modelos anêmicos, cada vez mais o código começa a ser transferido para os Controllers, tornando-os cheios, complexos e com grande facilidade de crashs.

Exemplo de Controller:

public class TicTacToeActivity extends AppCompatActivity {
private Board model;
/* View Components referenced by the controller */
private ViewGroup buttonGrid;
private View winnerPlayerViewGroup;
private TextView winnerPlayerLabel;
/**
* In onCreate of the Activity we lookup & retain references to view components
* and instantiate the model.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tictactoe);
winnerPlayerLabel = (TextView) findViewById(R.id.winnerPlayerLabel);
winnerPlayerViewGroup = findViewById(R.id.winnerPlayerViewGroup);
buttonGrid = (ViewGroup) findViewById(R.id.buttonGrid);
model = new Board();
}
/**
* Here we inflate and attach our reset button in the menu.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_tictactoe, menu);
return true;
}
/**
* We tie the reset() action to the reset tap event.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_reset:
reset();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* When the view tells us a cell is clicked in the tic tac toe board,
* this method will fire. We update the model and then interrogate it's state
* to decide how to proceed. If X or O won with this move, update the view
* to display this and otherwise mark the cell that was clicked.
*/
public void onCellClicked(View v) {
Button button = (Button) v;
int row = Integer.valueOf(tag.substring(0,1));
int col = Integer.valueOf(tag.substring(1,2));
Player playerThatMoved = model.mark(row, col);
if(playerThatMoved != null) {
button.setText(playerThatMoved.toString());
if (model.getWinner() != null) {
winnerPlayerLabel.setText(playerThatMoved.toString());
winnerPlayerViewGroup.setVisibility(View.VISIBLE);
}
}
}
/**
* On reset, we clear the winner label and hide it, then clear out each button.
* We also tell the model to reset (restart) it's state.
*/
private void reset() {
winnerPlayerViewGroup.setVisibility(View.GONE);
winnerPlayerLabel.setText("");
model.restart();
for( int i = 0; i < buttonGrid.getChildCount(); i++ ) {
((Button) buttonGrid.getChildAt(i)).setText("");
}
}
}
view raw controller.java hosted with ❤ by GitHub
  • MVP: Esta arquitetura quebra o Controller de modo que o acoplamento de View/Activity pode ocorrer sem amarrá-lo ao restante das responsabilidades do “Controller”. Logo:

MVP Example

Model View Presenter
Igual ao MVC / Nenhuma mudança Neste caso, a Activity/Fragment agora é considerada parte da View. A boa prática é ter uma Activity implementando uma interface de exibição para que o Presenter tenha uma interface para codificar. Com isto é eliminado o acoplamento e permite testes unitários. Idêntico ao Controller do MVC, exceto por ele não estar vinculado ao View, apenas a uma interface, com isto ele não mais gerencia o tráfego de solicitações recebidas, como é feito no Controller. Assim aborda as preocupações de testabilidade, modularidade e flexibilidade que apresentam com o MVC.
  • Vantagens: Ao invés de dizer a View como exibir algo, ele apenas delega o que exibir. Assim podemos testar com facilidade a lógica do Presenter, pois não está acoplada a View ou API específica do Android.
  • Desvantagens:
    • Manutenção: Os Presenters, assim como os Controllers, são propensos a colecionar lógica comercial adicional, espalhados com o tempo.
    • Eventualmente, os desenvolvedores deparam-se com grandes Presenters difíceis de separar.

Exemplo de MVP:

public class TicTacToePresenter implements Presenter {
private TicTacToeView view;
private Board model;
public TicTacToePresenter(TicTacToeView view) {
this.view = view;
this.model = new Board();
}
// Here we implement delegate methods for the standard Android Activity Lifecycle.
// These methods are defined in the Presenter interface that we are implementing.
public void onCreate() { model = new Board(); }
public void onPause() { }
public void onResume() { }
public void onDestroy() { }
/**
* When the user selects a cell, our presenter only hears about
* what was (row, col) pressed, it's up to the view now to determine that from
* the Button that was pressed.
*/
public void onButtonSelected(int row, int col) {
Player playerThatMoved = model.mark(row, col);
if(playerThatMoved != null) {
view.setButtonText(row, col, playerThatMoved.toString());
if (model.getWinner() != null) {
view.showWinner(playerThatMoved.toString());
}
}
}
/**
* When we need to reset, we just dictate what to do.
*/
public void onResetSelected() {
view.clearWinnerDisplay();
view.clearButtons();
model.restart();
}
}
view raw Presenter.java hosted with ❤ by GitHub
  • MVVM: junto com o Data Binding, esta arquitetura tem como benefícios testes mais fáceis e modularidade, ao mesmo tempo que reduz a quantidade de código que temos que escrever para conectar o Model com a View. Também suporta ligação bidirecional entre View e ViewModel, com isto nos permite ter propagação automática de mudanças. MVVM Example
Model View ViewModel
Igual ao MVC e MVP / Nenhuma mudança A View liga-se a variáveis ​Observable ​​e ações expostas pelo ViewModel de forma flexível. O ViewModel é responsável por expor métodos, comandos e propriedades que mantém o estado da View, assim como manipular a Model com resultados de ações da View e preparar dados Observable necessários para a exibição. Ele também fornece ganchos para que a View passe eventos para o Model. No entanto o ViewModel não está vinculado à View. Existe uma relação de muitos-para-um entre a View e ViewModel, o que significa que uma ViewModel pode mapear muitas Views.
  • Vantagens: Os testes unitários se tornam ainda mais fáceis, porque você realmente não tem dependência na View. Ao testar, você só precisa verificar se as variáveis Observable ​​são definidas adequadamente quando o Model muda.
  • Desvantagens: As Views podem se ligar (bind) a ambas as variáveis ​​e expressões, adicionando código efetivamente ao nosso XML. Para evitar isso, sempre obtenha valores diretamente do ViewModel em vez de tentar calcular utilizando Lambda no XML, como no último exemplo para trabalhar com VISIBLE ou GONE.

Exemplo de MVVM:

public class TicTacToeViewModel implements ViewModel {
private Board model;
/*
* These are observable variables that the viewModel will update as appropriate
* The view components are bound directly to these objects and react to changes
* immediately, without the ViewModel needing to tell it to do so. They don't
* have to be public, they could be private with a public getter method too.
*/
public final ObservableArrayMap<String, String> cells = new ObservableArrayMap<>();
public final ObservableField<String> winner = new ObservableField<>();
public TicTacToeViewModel() {
model = new Board();
}
// As with presenter, we implement standard lifecycle methods from the view
// in case we need to do anything with our model during those events.
public void onCreate() { }
public void onPause() { }
public void onResume() { }
public void onDestroy() { }
/**
* An Action, callable by the view. This action will pass a message to the model
* for the cell clicked and then update the observable fields with the current
* model state.
*/
public void onClickedCellAt(int row, int col) {
Player playerThatMoved = model.mark(row, col);
cells.put("" + row + col, playerThatMoved == null ?
null : playerThatMoved.toString());
winner.set(model.getWinner() == null ? null : model.getWinner().toString());
}
/**
* An Action, callable by the view. This action will pass a message to the model
* to restart and then clear the observable data in this ViewModel.
*/
public void onResetSelected() {
model.restart();
winner.set(null);
cells.clear();
}
}
view raw ViewModel.java hosted with ❤ by GitHub

Bibliografia

@ksdrof500 - Android MVC x MVP x MVVM qual Pattern utilizar

Inscreva-se em nossa newsletter

E receba as novidades da Studio em seu e-mail.

* requeridos

Camila L. Oliveira
Escrito por Camila L. Oliveira
Tecnóloga em Análise e Desenvolvimento de Sistemas, Bacharel em Administração Pública, Programadora de Computadores e Dispositivos Móveis e Técnica em Informática para Internet. Com experiências nas empresas TCS e BRQ, atuando no desenvolvimento de soluções aos clientes há mais de 2 anos.
//Insert Firebase