O documento discute o uso de Loaders no Android para carregar dados de forma assíncrona e monitorar alterações na fonte de dados. Os Loaders carregam dados em segundo plano e atualizam a interface do usuário quando os dados são modificados, evitando travamentos. O documento também explica como implementar Loaders e como eles facilitam o gerenciamento de operações longas no ciclo de vida de Activities e Fragments.
1. Android – Carregando dados com Loaders
●
Motivação:
➔
Organização das Threads no Android
➔
UI Thread e operações longas
➔
Operações longas em outras threads
●
Vida sem os Loaders
●
Introdução aos Loaders
●
Prática
2. Apresentação
Fernando Camargo:
● Graduando do curso de Engenharia de Computação na
UFG
● Estuda Java desde 2009 e Android desde o início de
2012
● OCJP 6
● Desenvolve para Java EE, Android e Grails
● Fazendo estágio na Fibonacci Soluções Ágeis
3. Motivação
● Como são organizadas as threads no Android?
● Qual thread é responsável pela criação da interface com o
usuário?
● Qual é a diferença dela para threads comuns?
● Outras threads podem modificar a interface com o usuário?
● O que acontece quando a thread responsável por tal
interface fica muito tempo em uma operação longa?
● Como rodar operações longas e modificar a interface com o
usuário de forma segura?
4. Organização das Threads
A organização das threads no sistema Android é bem
simples:
● UI Thread
Thread principal e única responsável por construção e
atualização da tela. Todo o ciclo de vida de uma Activity roda
nessa thread. Nenhuma outra thread pode modificar a tela.
● Demais threads
Geralmente lançadas para executar tarefas em paralelo. Não
pode fazer qualquer modificação na tela.
5. UI Thread e operações longas
Toda e qualquer operação longa (interações com o banco
de dados e a internet, por exemplo) deve ser evitada na UI
Thread, pois pode causar travamento e ANRs (Application
Not Responding).
6. Operações longas em outras threads
Todas as operações longas devem ser feitas em outras
threads. Porém, tais threads não podem alterar a tela.
Então como podemos atualizá-la ao fim da operação?
● Handler
● runOnUiThread(Runnable)
● AsyncTask
● Loaders
7. Handler
Cria-se uma nova thread para executar a operação longa.
Ao fim da mesma, usa-se o handler para se comunicar com
a UI Thread, para que essa faça as atualizações na tela.
Devido à sua complexidade, não é amplamente usado.
9. AsyncTask
Uma forma mais simples de executar tarefas em segundo plano e
fazer atualizações na tela. Seu uso substitui o uso dos
complicados Handlers.
Trata-se de uma classe abstrata com os seguintes métodos a
serem implementados:
● onPreExecute: Executado na UI Thread antes da execução da
tarefa.
● doInBackground: Executado em segundo plano por outra
thread.
● onPostExecute: Executado após a execução da tarefa na UI
Thread. Geralmente usado para atualizar a tela.
10. AsyncTask (2)
O desenvolvedor deve estender essa classe
implementando pelo menos o método doInBackground.
Com uma instância dessa subclasse, deve-se chamar o
método run. Também é possível cancelar a tarefa usando o
método cancel.
11. Vida sem os Loaders
Essas dumas formas de executar operações longas em
outra thread e atualizar a tela (em especial AsyncTask), são
ótimas. Mas e quando precisamos especificamente carregar
e monitorar uma fonte de dados que alimentará nossa
aplicação?
Com AsyncTask, teríamos uma tarefa responsável por
carregar os dados e outra para monitorar as modificações
no mesmo, sendo que essa deveria ser reinicializada após
seu término.
Implementar isso pode ser complicado e possuir erros.
12. Introdução aos Loaders
Foram introduzidos no Android 3.0 e portados através de
uma biblioteca de compatibilidade para versões anteriores.
Tornam fácil o carregamento de dados em Activity's e
Fragment's (esse não será apresentado aqui).
● Fornecem carregamento assíncrono de dados.
● Monitoram a fonte de dados e entregam novos
resultados quando o conteúdo muda.
● Reconectam automaticamente quando há uma mudança
de configurações (quando o usuário vira o smartphone,
por exemplo).
13. LoaderManager
Gerenciador dos Loaders de uma determinada Activity ou
Fragment. Ajuda a aplicação a gerenciar operações longas
em conjunção com o ciclo de vida de seu(sua) respectivo(a)
Activity ou Fragment.
Com a biblioteca de compatibilidade, pode ser obtido através
do método getSupportLoaderManager(), presente na classe
FragmentActivity.
Os Loaders são iniciados através de seu método initLoader
e reiniciados através de seu método restartLoader. Um
Loader também pode ser recuperado através do método
getLoader.
14. LoaderCallbacks
Uma interface a ser implementada e passada para o
LoaderManager no momento da (re)inicialização de um
Loader. Os métodos dessa interface rodaram na UI Thread.
● onCreateLoader: Método responsável por retornar uma
instância de Loader a ser usado pelo LoaderManager.
● onLoadFinished: Método chamado após a chegada de
novos resultados. Geralmente usado para atualizar a tela
com os novos dados.
● onLoaderReset: Método onde se deve limpar os dados
previamente carregados pelo Loader, pois tais dados ficarão
indisponíveis.
15. Loader
Classe abstrata que realiza carregamento assíncrono de
dados. Enquanto ativos, também devem monitorar a fonte
de dados e entregar novos resultados quando o conteúdo
mudar.
Geralmente, deve-se criar uma subclasse da classe
AsyncTaskLoader (classe que utiliza AsyncTask para
realizar o carregamento e monitoramento em outra thread).
Uma subclasse de AsyncTaskLoader pode sobrescrever os
métodos: loadInBackground, deliverResult,
onStartLoading, onStopLoading, onCanceled, onReset,
entre outros.
16. CursorLoader
Já existe implementada a classe CursorLoader, subclasse
de AsyncTaskLoader. Através dela, pode-se usar Loaders
com Cursor de um banco de dados sem se preocupar em
criar uma subclasse de Loader. O monitoramento de dados
é feito através de um Observer que observa notificações do
Content Provider.
17. Prática
Aplicativo de leitura de contatos cadastrados no Aplicativo
apresentado anteriormente. Esse aplicativo será bem
simples e fará o seguinte:
● Apresentará uma tela de login para o usuário logar em
sua conta.
● Se comunicará com um webservice para fazer
autenticação.
● Possuirá um Loader que se comunicará com um
webservice para carregar os contatos.