Utilizando o padrão Delegate no Android

(Última atualização em: 22 de março de 2016)

Quando vamos fazer uma aplicação mobile, é muito comum termos que consumir dados de um web service. 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 no Alura temos vários cursos sobre Android.
Se preferir aulas presenciais, veja os cursos da Caelum 🙂

  • Weverton Reis

    Parabéns, excelente post.

    • Matheus Brandino

      Muitíssimo obrigado Weverton !! Fico muito contente que tenha curtido o post 🙂

  • william

    Muito bom Matheus. Parabéns!

  • Achei estranho a interface estar declarada com um nome e na Task estar sendo declara com outro. Ex: “BuscaMaisNovidades” -> “BuscaMaisNovidadesDelegate”. De resto excelente post.

    • Matheus Brandino

      Raul, obrigado pelo comentário, acabei de arrumar aqui.

  • Fabiano França

    Parabéns pelo post. Ficou muito bom!

  • Wesley Tavares

    Ótima dica. Parabéns Matheus.

Próximo ArtigoValidando dados com expressões regulares no Java