quarta-feira, 30 de outubro de 2013

Banco de dados - Parte 2

Olá à todos.

Neste post continuaremos a explicar como interagir com Banco de Dados em Android. Criaremos um exemplo de banco de dados mais avançado, utilizando o conceito de ContentProvider.

Esta é a metodologia mais indicada pelos Guidelines do Android. Nela, todas as operações CRUD que realizamos no post anterior são feitas de modo mais simplificado.

Para criar e atualizar um banco de dados em sua aplicação Android, precisamos criar uma subclasse da classe SQLiteOpenHelper. No construtor desta subclasse, devemos chamar o método super() de SQLiteOpenHelper, especificando o nome do banco de dados e a versão corrente do banco de dados.

Nesta classe precisamos sobrescrever (Override) os seguintes métodos, para criar e atualizar o banco de dados:


  • onCreate() → É chamado se o banco de dados for acessado, mas ainda não tiver sido criado.
  • onUpgrade() → Chamado se a versão do banco de dados foi incrementada no código-fonte da aplicação. Este método permite atualizarmos um banco de dados existente, ou então deletar o banco de dados existente, e recriá-lo via método onCreate().


Ambos os métodos recebem um objeto SQLiteDatabase como parâmetro, que é a representação do banco de dados em Java.

A classe SQLiteOpenHelper possui os métodos getReadableDatabase() e getWriteableDatabase() para obter acesso à um objeto SQLiteDatabase, tanto em modo de leitura ou escrita.

As tabelas do banco de dados devem ter um identificador _id para a Primary Key da tabela. Vários métodos em Android se apoiam neste padrão.
Para nosso exemplo, utilizaremos um gerenciador de instrumentos musicais.

Ele possui os pacotes bean, dao e view. Logo, difere do post anterior do Blog pela exclusão do pacote impl, uma vez que, desta vez, no pacote dao o acesso ao banco de dados já está sendo realizado.

Vamos começar a destrinchar este aplicativo pelo pacote bean. Neste pacote temos a classe Guitarra.class. Ela é um bean assim como descrito neste post do Blog. Porém, possui algumas diferenças:


  • Ela possui a constante public static String[] colunas, que será utilizada toda vez que a tabela Guitarra for acessada no banco de dados. Mais à frente esta constante será melhor explicada.
  • Possui a classe interna Guitarras.


Esta classe interna possui muitas informações interessantes. É uma classe representa as colunas do banco de dados. É filha de BaseColumns, que já define (_id e _count), para seguir o padrão Android.

Esta classe possui algumas constantes (NOME, ANO, COR), que são os nomes das colunas da tabela Guitarra.




Já no pacote dao temos 3 classes: RepositorioGuitarra.java, RepositorioGuitarraScript.java, e a já citada SQLiteHelper.java. Nas 2 primeiras, temos tudo que precisamos para acessar o banco de dados de forma direta. Já na classe SQLiteHelper.java, temos os métodos onCreate() e onUpgrade(), como já citado no início deste post.

Vamos começar a destrinchar o pacote dao pela classe SQLiteHelper.java. Eis a classe, abaixo: 



Podemos ver acima os atributos mScriptSQLCreate e mScriptSQLDelete.


E acima, os atributos mScriptSQLCreate e mScriptSQLDelete são inicializados no construtor da classe, e o método onCreate() executa o comando advindo de mScriptSQLCreate.



E acima, o método onUpgrade(), que executa o SQL advindo de mScriptSQLDelete, que cada mais faz do que deletar o banco e chamar o método onCreate(), criando-o novamente.

Já as classes RepositorioGuitarra.java e RepositorioGuitarraScript.java serão destrinchados logo abaixo. Primeiramente, a classe RepositorioGuitarraScript.java.

Nesta classe temos basicamente os dados que inicializarão a classe SQLiteHelper.java. Tais dados são as constantes SCRIPT_DATABASE_CREATE, SCRIPT_DATABASE_DELETE, NOME_BANCO e VERSAO_BANCO. Isto pode ser observado logo abaixo: 



A inicialização destas constantes é feita no construtor da classe:



Por fim, nesta classe, temos o método fechar(), que fecha a conexão com o banco de dados.


Assim, pudemos notar que a classe RepositorioGuitarraScript.java funciona como um intermediador com a classe SQLiteHelper.java. Mais à frente nesta seção veremos que esta classe será utilizada bastante por telas do pacote view. Ou seja, a classe RepositorioGuitarraScript.java faz o papel de “conexão” entre os pacotes dao e view.

Agora, iremos falar da última classe do pacote dao, a classe RepositorioGuitarra.java. Sobre esta classe, ela se assemelha muito à classe BancoDaoImpl.java (citada neste post do Blog). Porém, possui algumas sutis diferenças.

Nesta classe temos 12 métodos que fazem acesso direto ao banco de dados, utilizando-se da classe Cursor, e também da classe ContentValues. A classe ContentValues é uma das sutis diferenças. Abaixo podemos notar o método inserir(), e como uma variável do tipo ContentValues é utilizada.


Repare que a classe interna Guitarras, que foi definida em Guitarra.java, do pacote bean, é chamado no método acima. Por sua vez, o método inserir() chama um Override dele mesmo, cuja implementação pode ser vista abaixo. Repare que o método que utiliza diretamente o tipo ContentValues é o método insert(), da classe SQLiteDatabase (advinda do atributo mDb).


Comparado ao método de acesso de dados explicado no último post do Blog, o que temos de diferente é o acesso aos dados do banco feito de forma mais facilitada. Repare que no método acima, em apenas 1 linha e com 3 argumentos, temos a persistência de dados no banco através da classe ContentValues. Isto também se repete na classes atualizar().


Já na classe delete() não utilizamos ContentValues, pois não precisamos armazenar nenhum objeto à ser inserido ou atualizado no banco. O que utilizamos é o método delete() (de forma direta), da classe SQLiteDatabase (advinda do atributo mDb).


Repare também que nesta classe a listagem e leitura de dados do banco é realizada obrigatoriamente com retorno do tipo Cursor.


Com tudo isso, podemos concluir que um ContentProvider ajuda bastante no acesso à bancos de dados. Porém, ainda não elimina o uso de tipos Cursor. Por fim, falaremos do pacote viewNeste pacote temos 4 classes: CadastroGuitarrasActivity.java, EditarGuitarraActivity.java, PesquisarGuitarraActivity.java e GuitarraListAdapter.java. Destas, apenas GuitarraListAdapter.java não é uma tela (pois é um Adapter de lista).

Das 3 telas citadas acima, apenas a tela CadastroGuitarrasActivity.java faz acesso à bancos de dados, utilizando-se de chamadas à classes e métodos do pacote dao. As classes EditarGuitarraActivity.java e PesquisarGuitarraActivity.java não fazem acesso ao banco, uma vez que chamam diretamente a classe CadastroGuitarrasActivity.java (que por sua vez faz o acesso ao banco de dados).

Logo, falaremos sobre a classe CadastroGuitarrasActivity.java.


Acima, podemos notar que temos um atributo do tipo RepositorioGuitarra, que fará o acesso direto com o pacote dao.


Acima temos os métodos onCreate(), onDestroy() e onCreateOptionsMenu(). Destes 3, os 2 primeiros que utilizam acesso direto ao banco de dados. Em onCreate() o banco é inicializado através do construtor mRepositorio = new RepositorioGuitarraScript(this); e em onDestroy() o banco é fechado através do comando mRepositorio.fechar();.



Acima temos apenas o método de Menu.




E agora, temos 2 métodos derivados de classes Activity, e dentro deles, são chamados os métodos editarGuitarra() e atualizarLista(). O método editarGuitarra() é chamado quando clicamos em um item da lista, e o método atualizarLista() é executado após qualquer item da lista tiver sido alterado.



Por fim, a implementação dos métodos citados anteriormente é mostrada acima. Repare que em atualizarLista(), já no primeiro comando do método o repositório é diretamente chamado. E em editarGuitarra() a classe EditarGuitarraActivity.class é chamada, e por sua vez, na seção “Métodos de banco de dados” desta classe, a tela atual (CadastroGuitarrasActivity.java) é chamada mais uma vez, referenciando novamente os repositórios de banco de dados.

Isto pode ser feito porque o repositório é um atributo (variável) do tipo static. Assim, chegamos ao fim deste post e do aplicativo de Guitarras.

Ainda podemos melhorar o acesso ao banco e o fluxo entre as telas do nosso aplicativo. Isto será mostrado no próximo post deste Blog.


-----

E aqui terminamos mais um tópico do blog.


Caso alguém tenha uma dúvida, crítica ou sugestão, sinta-se à vontade.

Nenhum comentário:

Postar um comentário