Disparando eventos customizados no Android

Disparando eventos customizados no Android
erich.egert
erich.egert

Compartilhe

Na plataforma Android, o uso de Fragments para flexibilizar o desenvolvimento é uma prática cada vez mais difundida, em especial para aplicações que precisam rodar em tablets. Através dos Fragments é possível isolar o comportamento de pequenos trechos da tela, ajudando a reduzir a quantidade de código nas activities e permitindo maior flexibilidade no momento de fazer a mesma aplicação rodar em Smartphones e Tablets.

Uma questão relevante nesse cenário é: O que devemos fazer quando um evento em um Fragment impacta em outros Fragments?

Suponha uma tela de um Tablet no qual existam 3 Fragments. À esquerda uma listagem de posts de um blog, no canto superior direito um Fragment que mostra os detalhes do post selecionado, no canto inferior direito para a criação de uma resposta para o post selecionado da listagem:

Banner da Escola de Mobile: Matricula-se na escola de Mobile. Junte-se a uma comunidade de mais de 500 mil estudantes. Na Alura você tem acesso a todos os cursos em uma única assinatura; tem novos lançamentos a cada semana; desafios práticos. Clique e saiba mais!

tela_3_fragmentsTela da aplicação com 3 fragments

Quando clicamos em um item do ListView precisamos passar esse item para os demais Fragments, podemos fazer isso diretamente no Fragment que apresenta a listagem na tela:

 getListView().setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> adapter, View view, int posicao, long id) { BlogPost postSelecionado = (BlogPost) adapter.getItemAtPosition(posicao); FragmentManager manager = getFragmentManager(); PostSelecionadoFragment telaDetalhesPost = (PostSelecionadoFragment) manager.findFragmentById(R.id.direita\_superior); telaDetalhesPost.lidaCom(postSelecionado); NovoPostFragment telaNovoPost = (NovoPostFragment) manager.findFragmentById(R.id.direita\_inferior); telaNovoPost.lidaCom(postSelecionado); PostsActivity activity = (PostsActivity) getActivity(); activity.lidaComSelecao(postSelecionado); } }); 

Mas será que é responsabilidade de um Fragment conhecer os demais? Podemos delegar a responsabilidade de lidar com a tela como um todo para a Activity que já a está gerenciando , isolando todo o código acima:

 getListView().setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> adapter, View view, int posicao, long id) { BlogPost postSelecionado = (BlogPost) adapter.getItemAtPosition(posicao); PostsActivity activity = (PostsActivity) getActivity(); activity.lidaComSelecao(postSelecionado); } }); 

O problema é que acoplamos nosso Fragment de listagem com uma Activity em específico, dificultando seu reaproveitamento. Se resolvermos dar suporte a smartphones, inclusive de tamanho de tela pequena, precisaremos quebrar essa tela em duas ou até três, tornando o método da Activity que lida com a seleção cada vez mais complexo.

Uma maneira de reduzir o acoplamento é trabalhar com mensagens, de maneira semelhante à que os desenvolvedores no iOS fazem com o NSNotificationCenter.

Na seleção de um item, podemos usar o LocalBroadcastManager para disparar uma mensagem de broadcast que não sairá dos limites de nossa aplicação (ajudando nos quesitos segurança e performance).

 getListView().setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> adapter, View view, int posicao, long id) { BlogPost postSelecionado = (BlogPost) adapter.getItemAtPosition(posicao); Intent intent = new Intent("post-foi-selecionado");

intent.putExtra("blogpost", post); LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } }); 

Agora podemos registrar os Fragments interessados nesse evento:

 public class BlogPostSelecionado extends BroadcastReceiver { private FragmentObservador observador;

public static BlogPostSelecionado registraParaLidarComASelecao(FragmentObservador o) { BlogPostSelecionado receiver = new BlogPostSelecionado(); receiver.observador = o; LocalBroadcastManager.getInstance(o.getContext()) .registerReceiver(receiver, new IntentFilter("post-foi-selecionado"));

return receiver; } } 

Agora os Fragments interessados em nosso evento apenas precisam implementar a interface FragmentObservador:

 public interface FragmentObservador { Context getContext(); void lidaCom(Post post); } 

Dessa forma invertemos a responsabilidade de propagar o evento para a plataforma, reduzindo o acoplamento e facilitando a manutenção.

Querendo aprender desenvolvimento Android? Conheça o nosso curso!

Veja outros artigos sobre Mobile