Desenvolvendo para Android – Como persistir dados offline com SQLite

Standard

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.

Visualização da estrutura default- Android

Visualização da estrutura default- Android

ProjectView

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:

  1. Clicar em Edit Configurations na lista que aparece antes da setinha verde do Run do IDE.

EditConfigurations

2. Adicionar uma nova configuração, clicando o botão verde com o sinal “+” mais a esquerda da janela aberta e escolher android tests.

AndroidTests

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.

Configurations

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.

Tests Passed

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

Leave a comment