Hello Desenvolvedores, espero que estejam todos muito bem e bem dispostos para continuarmos com os posts da nossa serie. Só para lembrar e actualizar os que não tenham lido, no post anterior vimos:
- como conectar a uma API utilizando as classes HttpUrlClient,
- O que é a main thread e porque não devemos realizar operações que podem ser longas( realizar um pedido a uma api, descarregar ou descodificar uma imagem),
- Como utilizar a classe AsyncTask para realizar operações fora da Main thread
- e finalmente como descodificar a resposta do JSON disponibilizada por um pedido a API do openweather.org utilizando as classes JSONObject .
Só com o post anterior é possível criar aplicações para mostrar o feed de um jornal, tweets de um certo hashtag ou dados de temperatura como no nosso exemplo e da aplicação sunshine no curso do Udacity e disponibilizar no playstore. Só que apesar de funcionar, implementar uma solução desse jeito e publicar não seria uma boa experiência para o utilizador pois toda vez que ele abrisse a aplicação ou reiniciasse uma activity por algum motivo teria de refazer os pedidos a API o que resultaria em um gasto constante de dados e de bateria por estar a utilizar o rádio do dispositivo de forma irresponsável.
Para resolver esses pequenos inconvenientes, o android oferece várias opções que permitem persistir os dados no dispositivo para que estejam disponíveis mesmo quando os dispositivo esta desligado da rede. As opções existentes são:
- SharedPreferences : Mecanismo que permite guardar como forma de chave- valor informações dos tipos de dados primitivos. Muito prático para guardar algumas configurações como um boolean para verificar se o utilizador já fez o login antes mas pouco eficaz para guardar dados das estruturas complexas que normalmente temos nas aplicações. Este mecanismo é seguro pois só é possível ter acesso aos dados dentro da nossa aplicação.
- Internal Storage (Memoria interna do dispositivo): este mecanismo permite guardar ficheiros directamente na memória do dispositivo. E para esclarecer qualquer questão, a escrita e leitura de ficheiros é exactamente como e feita tradicionalmente no java. Neste mecanismo só é possível ter acesso aos ficheiros pela aplicação e esta é toda apagada no momento que a aplicação é desinstalada.
- External Storage(Memoria externa) : Este mecanismo permite guardar ficheiros directamente em uma memória auxiliar como microSD e tem a grande desvantagem de não oferecer segurança pois os ficheiros todos podem ser lidos e modificados pelo utilizador caso esteja a utilizar a memória no modo “mass storage”.
- SQLite Database : O android oferece para base de dados em SQLite que podemos aceder pelo nome da base de dados apenas dentro da aplicação em que ela foi criada. Este mecanismo possui a vantagem de ser seguro e pratico para armazenar estruturas complexas.
A minha opinião é de que todas as opções citadas acima são interessantes dependendo do caso em que precisaríamos utilizar mas para este post iremos utilizar a ultima opção que é o SQLite Database.
Sendo assim, neste post iremos ver os seguintes pontos:
- Criar uma classe que vai definir o contracto ou esquema da nossa base de dados.
- Utilizar a classe SQLHelper para criar a base de dados
- Utilizar o Framework de testes do android studio para realizar os testes em que iremos inserir, actualizar e remover os dados nas tabelas da nossa base de dados.
Começando pelo primeiro ponto, vamos pegar o projecto do post anterior, criar um pacote com o nome data como mostra a figura abaixo. De seguida vamos criar um classe chamada WeatherContract como esta no gist AQUI.
A classe que acabamos de criar irá conter classes internas que irão representar cada tabela da nossa base de dados, possuindo o nome das colunas e outros detalhes que iremos utilizar ao estudar content providers em posts mais a frente.
Criado o nosso contracto, vamos agora criar uma classe WeatherSQLHelper que vai extender a classe SQLiteOpenHelper. O SQLiteHelper, é uma classe que nos ajuda na criação, e gestão de versões da base de dados.
Para utilizar esta classe e criar uma base de dados, devemos criar um construtor que tenha a chamada para o método super, e reescrever o método onCreate(SQLiteDatabase db) que é o método onde todo processo de criação da base de dados e das respectivas tabelas é efectuado . Dentro desta classe definimos ainda parâmetros como o nome da base de dados, a versão.
Ate então, o que nos resta, é criar as queries para criação de tabelas usando o auxilio das colunas definidas estaticamente na classe do contracto acima.
Após criadas as strings para a criação das colunas, vamos , dentro do metodo onCreate, criar as tabelas utilizando o método execSQL(String string) da classe SQLiteDatabase que é passada como construtor para o método com mostra o gist completo do helper AQUI.
Finalmente temos o nosso contracto criado, a base de dados e as tabelas.
Quando comecei a programar para android e mexi com o SQLite pela primeira vez, na hora de testar , tive de perder muito tempo para criar uma UI que me permitisse testar as operações de inserção, leitura e actualização para no fim ficar devastado ao descobrir que tinha um erro e não tinha nada haver com a UI que tinha perdido tanto tempo a criar.
Felizmente, as nossas ferramentas de desenvolveram tanto que hoje em dia o android studio possui um Framework de testes que nos permite testar só esta parte da base de dados sem que tenhamos de fazer o mesmo trabalho que tive aquela altura, permitindo testar a aplicação tomando cada parte da aplicação independente do resto da implementação.
Para começar, devemos dentro da nossa aplicação, do lado esquerdo onde tem a estrutura do projecto mudar a virtualização da estrutura do projecto para “Project” pois este pode estar em mais duas formas “Android” por default our “package”. Para tal vejam como o fazer nas figuras abaixo.
A segunda figura mostra que dentro da pasta app->src, temos uma pasta chamada androidTest. Esta pasta é automaticamente criada pelo android studio quando se cria um novo projecto, e esta contem os ficheiro de testes que eventualmente podemos querer utilizar na nossa aplicação, neste caso para testar a nossa base de dados. Vamos dentro do pacote principal dentro da pasta criar uma classe TesteDb e fazer com que a mesma extenda AndroidTestCase.
Feito isto para dar continuidade ao processo, antes de começar a escrever os métodos do teste, devemos configurar o Android Studio para que execute os testes como uma variante separada da nossa aplicação. Para isso basta:
- Clicar em Edit Configurations na lista que aparece antes da setinha verde do Run do IDE.
2. Adicionar uma nova configuração, clicando o botão verde com o sinal “+” mais a esquerda da janela aberta e escolher android tests.
3. Copiar as configurações como estão na figura abaixo. Note que o mais importante e configurar o nome (Name) , escolher o “module” que normalmente costuma ser o “app” e definir que deve sempre mostrar a opção de escolher o dispositivo em que deseja executar os testes.
Concluídas as nossas configurações, vamos voltar para o ficheiro de testes e escrever os métodos como estão no gist AQUI.
Ao clicar na setinha verde para executar a configuracao de testes, se estiverem a utilizar um dispositivo real ira mostrar a tela normal para executar no dispositivo e os testes serao iniciados mostrando o resultado como na figura abaixo.
Com os testes efectuados e todos limpinhos, chegamos ao fim de mais um post e desta vez desafio-vos a implementar os testes que faltam como a inserção, leitura dos dados da previsão.
Mais uma vez obrigado pela atenção ao ler este post e espero poder ter contribuído no teu caminho de Ninja android dev.
Abraços!
DM
One thought on “Desenvolvendo para Android – Como persistir dados offline com SQLite”