Quando comecei minha jornada como desenvolvedor Android, as palavras “Arquitetura de Aplicativos Móveis” me causaram profunda perplexidade, o Google e os artigos sobre Habré me levaram a uma depressão ainda maior - olho para o livro e não vejo nada. Acho que se você está lendo este artigo, já estudou esse quadro mais de uma vez e tentou entender o que está acontecendo: O problema de entender a abordagem arquitetônica no desenvolvimento móvel, na minha opinião, está na abstração da própria arquitetura. Cada desenvolvedor tem sua própria visão de como implementar corretamente este ou aquele padrão. Exemplos mais ou menos decentes de implementação de MVP foram encontrados no setor de língua inglesa da Internet, o que não é surpreendente. Vejamos brevemente o que é o quê e passemos para um exemplo. Modelo - nível de dados. Não gosto de usar o termo “lógica de negócio”, por isso nas minhas aplicações chamo-o de Repositório e ele se comunica com o banco de dados e com a rede. Visualizar — nível de exibição. Será Activity , Fragment ou Custom View se você não gosta de dançar com pandeiro e interagir com o ciclo de vida. Deixe-me lembrá-lo que inicialmente todos os aplicativos Android estão subordinados à estrutura MVC , onde o Controller é uma Activity ou Fragment . Presenter é uma camada entre View e Model. A View transmite os eventos que lhe ocorrem, o apresentador os processa, se necessário, acessa o Modelo e retorna os dados para a View para renderização. Em relação ao Android e a um exemplo específico, destaco a parte importante – Contrato. Esta é a interface que descreve todas as interações entre os componentes acima. Para resumir a parte teórica:
- Ver sabe sobre o Presenter;
- O apresentador conhece View e Model (Repository);
- Modelo por si só;
- O contrato rege as interações entre eles.
MainContract
:
public interface MainContract {
interface View {
void showText();
}
interface Presenter {
void onButtonWasClicked();
void onDestroy();
}
interface Repository {
String loadMessage();
}
}
Por enquanto, estamos simplesmente destacando os 3 componentes da nossa aplicação futura e o que eles farão. A seguir descreveremos o Repositório:
public class MainRepository implements MainContract.Repository {
private static final String TAG = "MainRepository";
@Override
public String loadMessage() {
Log.d(TAG, "loadMessage()");
/** Здесь обращаемся к БД or сети.
* Я специально ничего не пишу, чтобы не загромождать пример
* DBHelper'ами и прочими не относяшимеся к теме an objectми.
* Поэтому я буду возвращать строку Сосисочная =)
*/
return "Сосисочная у Лёхи»;
}
}
Tudo fica claro com ele, apenas carregando e descarregando dados. O próximo é o apresentador:
public class MainPresenter implements MainContract.Presenter {
private static final String TAG = "MainPresenter";
//Компоненты MVP applications
private MainContract.View mView;
private MainContract.Repository mRepository;
//Сообщение
private String message;
//Обрати внимание на аргументы конструктора - мы передаем экземпляр View, а Repository просто создаём конструктором.
public MainPresenter(MainContract.View mView) {
this.mView = mView;
this.mRepository = new MainRepository();
Log.d(TAG, "Constructor");
}
//View сообщает, что кнопка была нажата
@Override
public void onButtonWasClicked() {
message = mRepository.loadMessage();
mView.showText(message);
Log.d(TAG, "onButtonWasClicked()");
}
@Override
public void onDestroy() {
/**
* Если бы мы работали например с RxJava, в этом классе стоило бы отписываться от подписок
* Кроме того, при работе с другими методами асинхронного андроида,здесь мы боремся с утечкой контекста
*/
Log.d(TAG, "onDestroy()");
}
}
Você se lembra que escrevi sobre dançar com pandeiro e o ciclo de vida? O Presenter vive enquanto vive o seu View, ao desenvolver cenários de usuário complexos, aconselho duplicar todos os callbacks do View no Presenter e chamá-los nos momentos apropriados, duplicando o ciclo de vida da Activity/Fragment, para entender a tempo o que precisa ser feito com os dados que estão atualmente pendurados no “interlayer”. E por fim, Visualize:
public class MainActivity extends AppCompatActivity implements MainContract.View {
private static final String TAG = "MainActivity";
private MainContract.Presenter mPresenter;
private Button mButton;
private TextView myTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Создаём Presenter и в аргументе передаём ему this - эта Activity расширяет интерфейс MainContract.View
mPresenter = new MainPresenter(this);
myTv = (TextView) findViewById(R.id.text_view);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresenter.onButtonWasClicked();
}
});
Log.d(TAG, "onCreate()");
}
@Override
public void showText(String message) {
myTv.setText(message);
Log.d(TAG, "showMessage()");
}
//Вызываем у Presenter метод onDestroy, чтобы избежать утечек контекста и прочих неприятностей.
@Override
public void onDestroy() {
super.onDestroy();
mPresenter.onDestroy();
Log.d(TAG, "onDestroy()");
}
}
O que está acontecendo?
- A atividade, também conhecida como View,
onCreate()
cria uma instância do Presenter em um método e passa para seu construtor. - Quando um Presenter é criado, ele recebe explicitamente uma View e cria uma instância de Repository (a propósito, ele pode se tornar um Singleton)
- Quando um botão é pressionado, o View bate no apresentador e diz: “O botão foi pressionado”.
- O apresentador recorre ao Repositório: “Baixe essa porcaria para mim”.
- O Repositório carrega e entrega as “coisas” ao Apresentador.
- Apresentador vira para Visualizar: “Aqui estão os dados para você, desenhe-os”
GO TO FULL VERSION