Muito bem Matheus, talvez eu tenha de expressado de forma muito superficial. Vamos lá.
-- Isolamento (ou encapsulação) quer dizer: Cada componente, classe ou objeto tem que saber fazer o seu trabalho, sem depender e sem interferir no trabalho de outros componentes, ou seja, o garçom anota o pedido, o ajudante corta os legumes e o cozinheiro administra a cozinha.
Daí vc me diz "Ah, mas eles precisam conversar e interagir, então um depende do outro". Sim, mas isso não quer dizer que, se o Garçom Zezinho faltar no trabalho, o Garçom Luizinho não possa assumir e dar continuidade no trabalho. Em outras palavras, se vc precisar trocar um componente (ou no caso do Android, estamos falando do lifecycle dos componentes e essa dança de destrói-recria-bind-fora-de-hora), cada um deles não pode "chashear" por causa disso.
No seu caso, o que venho sugerindo pra vc é:
- Um componente responsável pelo envio/recebimento das mensagens: um Service;
- Um componente responsável pelo "streaming" das músicas: outro Service;
- Um componente responsável por "manter" os dados: o ContentProvider;
- Um componente para cada conversa: o (Matrix)Cursor;
- Um componente para avisar quando o conteúdo (as mensagens) é modificado: o ContentObserver; ¹
- Um componente para visualizar/escrever as mensagens: o Fragment;
- Um componente para juntar tudo isso: a Activity;
"Conteúdo" é o termo para definir qualquer forma de informação, não apenas de banco de dados relacional (SQLite), mas também XML, Vídeo, áudio, TXT, Arrays e qualquer outra coisa. Suas mensagens são conteúdo, o streaming de áudio é conteúdo, as informações da rádio são conteúdo. Logo o ContentObserver, "observa" (viu a sutileza? rsrs) qualquer mudança em qualquer forma de conteúdo. Lembrete: ContentObserver é o nome do componente, mas vc pode ter dezenas deles, um para cada coisa.
Nota ¹: No caso do ContentObserver, ele é um componente que já é utilizado e implementado pela API do Android nos cursores e ListView's. Agora suponha que vc tenha duas conversas. Vc está na conversa "A", mas recebe uma mensagem na conversa "B" e quer fazer a aba daquela conversa "pisque" para o usuário. É aí que entra um ContentObserver customizado, q vc implementa para chamar o método que faz a aba piscar. Vc registra o ContentObserver quando o Fragment "sai de cena" (possivelmente no Fragment#onPause() ) e "desregistra" quando o Fragment voltar a ser visualizado na tela. Durante o período de vida do ContentObserver customizado, se uma nova mensagem chegar, o ContentObserver (que fica amarrado ao Cursor) é notificado. E sim, se vc tiver 20 abas "em segundo plano" vc teria 20 ContentObservers registrados. É pra isso que ele serve.
Só pra constar: até aqui estou falando de arquitetura, não de lifecycle ou "bindagem".
Agora, vamos pro lifecycle.
Quando a API do Fragment foi lançada, ficou claro que a Activity serviria apenas como "palco": os Fragments são os atores. Simples assim. Não só faz sentido, como eu diria que deveria ser a forma "oficial" em fazer o Context#bindService(Intent, ServiceConnection, int) dentro do Fragment, possivelmente no Fragment#onStart() e claro, chamando o Context#unbindService(ServiceConnection) no Fragment#onStop(). Dessa forma vc teria a certeza de que, tanto a instância do Service quando do Fragment são válidas quando vc precisar das informações necessárias.
Continuando, o Adapter é outra coisa que deveria ficar no Fragment, pois, partindo da lógica que sugeri onde o ContentProvider têm uma instância de um Cursor, no Fragment vc poderia fazer uma consulta utilizando a API do (Cursor)Loader (que é assíncrona) e recuperar um Cursor (que nada mais é que um MatrixCursor) e passar esse Cursor para um Adapter e então para uma ListView.
No caso de usar o Loader, vc chama getLoaderManager().initLoader(int, Bundle, LoaderCallbacks) a partir de, digamos, Fragment#onStart(). Só uma ressalva aqui: o Loader faz o gerenciamento do ciclo de vida dos cursores de forma automática, então, vc precisaria validar se ele não vai chamar um Cursor#close() e matar o MatrixCursor. O MatrixCursor, assim como eu disse, implementa o ContentObserver, seu Service poderia continuar recebendo as mensagens, enviando-as via ContentResolver#insert(Uri, ContentValues) e o ContentProvider adicionando-as no MatrixCursor e isso seria refletido direto no ListView sem que vc tenha que implementar nada (graças ao ContentObserver), porém, no caso de chamar o Cursor#close() isso poderia matar essa instância e prejudicar a recepção das mensagens.
Caso esse comportamento aconteça, vc tem duas opções:
- Ver se há alguma forma de "ignorar" o MatrixCursor#close(), tornando-o "imortal" rs; ou
- Ao invés de reter uma instância do MatrixCursor no ContentProvider, armazenar as mensagens em outra estrutura, como um ArrayList<> e no ContentProvider#query() retornar um Cursor que contém uma cópia das mensagens. O problema é que, ao receber uma nova mensagem a consulta teria que ser refeita. Vc já deve imaginar que o desempenho ficaria uma me***.
Concluindo, minha dica é: Não existem GRANDES problemas, apenas aqueles que vc não dividiu em pequenos problemas. Se está muito complicado coordenar tudo, divida a responsabilidade deles em componentes menores, mais simples...
You received this message because you are subscribed to the Google Groups "Android Brasil - Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to androidbrasil-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.






0 comentários:
Postar um comentário