Utilizando o padrão Delegate no Android

Vamos fazer a requisição em uma classe chamada WebClient
, ela será responsável por fazer a conexão com o servidor.
Nossa app é um catálogo de novidades aqui do Alura e, assim que abrirmos ela, será exibida uma listagem com todas as novidades. Essas novidades serão carregadas do servidor. Toda comunicação que fazemos com o servidor está na nossa AsyncTask
:
public class MinhaTask extends AsyncTask< Void, Void, List<Novidade> >{
private MinhaActivity activity;
public MinhaTask(MinhaActivity activity){
this.activity = activity; }
@Override protected List<Novidade> doInBackground(Void... params) {
WebClient webClient = new WebClient();
List<Novidade> novidades = webClient.post();
return novidades ; }
@Override protected void onPostExecute(List<Novidade> novidades) {
ListView lista = (ListView) activity.findViewById(R.id.lista);
lista.setAdapter(new ArrayAdapter(activity, android.R.layout.simple_list_item_1, novidades);
}
}

Legal, nosso código está funcionando! Mas o que estamos fazendo no onPostExecute? Estamos pegando a resposta e já estamos manipulando a tela.
Nossa AsyncTask
tem a responsabilidade apenas de fazer essa requisição mais pesada,o que de fato tem feito no método doInBackground
. Porém, no método onPostExecute
estamos manipulando a tela. Manipular a tela não é o foco da a AsyncTask
! Temos um especialista em manipulação de tela: nossa Activity
. Ela deve se virar para consumir os dados desta requisição.
@Override protected void onPostExecute(List<Novidade> novidades) {
activity.lidaComNovidades(novidades); }
Agora, nosso código está bem mais claro e deixou cada especialista fazer sua função. Nossa task para fazer a requisição pesada e nossa activity para manipular a tela.
Mas, qual é vantagem disso? Nossa AsyncTask
não precisa saber o que vamos fazer com os dados! Desta forma nosso código fica bem mais simples de dar manutenção e está bem desacoplado :)
Mas, e se tivermos a necessidade de fazer uma nova tela que também consumirá essa lista, mas fazer outro comportamento?
Já temos uma AsyncTask
que retorna exatamente o que precisamos: a listagem. Mas ela está acoplada diretamente com a Activity
que a chama, precisamos desacoplar nossa activity e garantir que receberemos um objeto que possua o método lidaComNovidades
. Para garantirmos que qualquer classe que nós formos usar possua este método, vamos estabelecer um contrato, atráves de uma Interface
:
public interface BuscaMaisNovidadesDelegate {
void lidaComNovidades(List<Novidade> novidades); }
Agora precisamos fazer nossa Activity
implementar nossa interface :
public class NossaActivity extends Activity implements BuscaMaisNovidades {
// todo código restante aqui !
@Override public void lidaComNovidades(List<Novidade> novidades) { // atualiza ListView com as novidades }
}
Agora, utilizando polimorfismo, podemos passar para nossa AsyncTask
a interface em seu construtor! Desta forma podemos reaproveitar nossa task em diversos locais, sempre passando uma Activity
que implemente a Interface
.
Chamamos este padrão de Delegate
:
public class MinhaTask extends AsyncTask< Void, Void, List<Novidade> >{
private BuscaMaisNovidadesDelegate delegate;
public MinhaTask(BuscaMaisNovidadesDelegate delegate){
this.delegate = delegate; }
@Override protected void onPostExecute(List<Novidade> novidades) {
delegate.lidaComNovidades(novidades); }
// resto do código }
Nosso código ficou bem mais desacoplado e agora podemos reaproveitar essa nossa AsyncTask
em qualquer outro projeto! O único pré-requisito é que este projeto tenha um Delegate
, pois podemos passar um objeto que implemente de Delegate
e terá os métodos necessários para desempenhar seu papel. Essa abordagem que estamos utilizando é um **Design Pattern**
chamado de Delegation
.
E ai gostou dessa dica? Quer conhecer mais sobre desenvolvimento Android e talvez iniciar sua carreira nessa área? Aqui na Alura temos vários cursos sobre Android. Se preferir aulas presenciais, veja os cursos da Caelum :)