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.

Banco de dados - Parte 1

Olá à todos.

Neste post começaremos a explicar como interagir com Banco de Dados em Android.

Em Android, o SGBD (Sistema Gerenciador de Banco de Dados) utilizado é o SQLite.

O SQLite é um banco de dados gratuito (Open Source). O SQLite possui características padrões à um banco de dados relacional, como a sintaxe SQL, transações e “prepared statements”. Seu banco de dados requer memória limitada em tempo de execução (aproximadamente 250 Kbytes), o que o torna um bom candidato para ser utilizado em dispositivos mobile.

O SQLite suporta os tipos TEXT (similar à String em Java), INTEGER (similar à Long em Java) e REAL (similar à Double em Java). Quaisquer outros tipos devem ser convertidos em algum destes, antes de serem salvos no banco de dados. O SQLite não valida se os tipos escritos nas colunas são de um tipo definido. Ou seja, podemos escrever um Integer em uma coluna String, e vice-versa.

Mais informações sobre o SQLite podem ser encontradas no site http://www.sqlite.org.

O SQLite fica armazenado internamente em cada dispositivo Android. Usar SQLite em Android não requer administração de seu banco de dados. Apenas temos que definir procedimentos SQL para criar e atualizar o banco de dados. Após isto, o banco de dados é automaticamente gerenciado pela plataforma Android.O acesso a um banco de dados SQLite envolve acessar o sistema de arquivos. Isto pode ser bem lento. Por este motivo, é recomendado realizar estas operações de forma assíncrona.Se sua aplicação cria um banco de dados, este banco por default será salvo no diretório DATA/data/APP_NAME/databases/FILENAME.

As partes do diretório acima são construídas baseadas nas seguintes regras:


  • DATA é o diretório ao qual o método Environment.getDataDirectory() retorna.
  • APP_NAME é o nome da sua aplicação.
  • FILENAME é o nome que você especificou para o banco de dados da sua aplicação.

Neste post aprenderemos a implementar um banco de dados em Android de diversas formas:


  • Básico, utilizando comandos SQL inteiros através do método execSql().
  • Avançado, utilizando ContentValues (que é o método aconselhado pela Google).
  • Utilizando Frameworks, que reduzem bastante nosso trabalho. Utilizaremos o ORMLite.


Implementaremos um CRUD (Create, Read, Update e Delete). Ou seja, implementaremos as operações básicas de SQL.

Banco de Dados Básico (execSql)


Para esta primeira metodologia, utilizaremos como exemplo um aplicativo de perguntas e respostas, um “Quizz”.

Nele conterão perguntas e respostas sobre Geografia. Serão 10 no total, e ao fim delas, será dado o resultado do Quizz ao usuário. Então, de onde começamos a implementação deste aplicativo?

Podemos concluir que este projeto em Android será dividido da seguinte forma:


  • Pacote com o modelo de dados. Ou seja, as classes que contém as entidades de Perguntas e Respostas. Um conceito bem conhecido sobre entidades representando dados de um banco de dados é o Bean. Por isto, criaremos um pacote chamado bean.
  • Pacote com as Activity’s, ou seja, as telas do aplicativo. Chamaremos este pacote de view.
  • Pacote com os métodos de manipulação do banco de dados. Para este exemplo, desmembraremos este pacote em dois diferentes pacotes:
    • O primeiro conterá apenas a definição dos métodos, com intuito didático. Chamaremos este pacote de dao.
    • O segundo conterá a implementação dos métodos do pacote acima. Chamaremos este pacote de impl.


Começaremos a demonstração deste aplicativo pelas classes do pacote bean.

Este pacote conterá as seguintes classes: Disciplina.java:



E Pergunta.java.



Podemos notar nestas classes algumas coisas em comum: ambas possuem os campos (que associaremos ao banco de dados) definidos como atributos, um construtor com argumentos e um construtor sem argumentos, um método toString(), e os métodos get() e set(). Desta forma, os objetos Pergunta e Resposta possuem tudo que precisamos para os utilizarmos nos pacotes view e impl.

Já no pacote dao temos os protótipos de métodos que farão a interação do aplicativo Android com o banco de dados. Seu nome é BancoDao.java.



Nela podemos ver alguns métodos genéricos (que funcionam tanto para Perguntas como Respostas), métodos específicos (como pesquisaPergunta() e insereResposta()), e métodos obrigatórios em qualquer conexão com banco de dados (criaConexao() e fechaConexao()).

Alguns métodos retornam um objeto do tipo Cursor. O que é um Cursor? Um Cursor se assemelha à um PreparedStatement, bastante utilizando em Java JDBC. Ele recebe o retorno de uma query de banco de dados.

Para entender melhor todos os métodos acima, precisamos dar uma olhada nas implementações destes.

Tais implementações estão no pacote impl. Este pacote possui apenas uma classe, chamada BancoDaoImpl.java. Ela possui mais de 200 linhas! Por ser uma classe extensa, ela será mostrada aqui em partes.

O início desta classe é mostrado abaixo. Nele temos:


  • CATEGORIA → Constante à ser utilizada pelos log() desta classe. A classe Log é uma classe que mostra ao usuário mensagens sobre o aplicativo. Elas podem ser de 5 tipos: d (debug), e (error), i (info), v (verbose), w (warn).
  • context → Variável que contém o contexto que utilizaremos para interagir com o banco de dados.
  • db → Variável que contém a instância do banco em nossa aplicação Android.
  • sql → Variável do tipo String que contém os comandos SQL à serem utilizadas nesta classe.
  • BANCO → Constante que define o nome do banco que criaremos.
  • TABELA_DISCIPLINA → Constante que possui o comando SQL para criar a tabela Disciplina. Esta tabela não foi referenciada anteriormente pois utilizaremos apenas uma disciplina em nosso exemplo: Geografia.
  • TABELA_PERGUNTA → Constante que possui o comando SQL para criar a tabela Pergunta.
  • TABELA_RESPOSTA → Constante que possui o comando SQL para criar a tabela Resposta.


Seguindo a explicação da nossa classe BancoDaoImpl.java, temos:



Acima temos 5 métodos. Vamos à eles:


  • BancoDaoImpl() → É o construtor da nossa classe. Nele o contexto que utilizaremos para acessar o banco de dados é setado.
  • criaConexao() → Função fundamental em qualquer aplicativo que utiliza bancos de dados. Com ela criamos a conexão com o banco. Isto é feito pelo método context.openOrCreateDatabase().
  • deletaRegistros() → Um dos 3 métodos genéricos da imagem acima. Neste métodos todos os registros do banco de dados são removidos. Isto é feito de forma manual através de 3 SQL’s que deletam as tabelas Disciplina, Pergunta e Resposta. Repare que o método mais importante de todos (que é o método que diretamente executa uma query no banco de dados) é o método execSQL()).
  • criaTabelas() → Este é o método que será chamado na Activity que utilizar acesso ao banco de dados. Ele faz tudo que precisamos para começar a manipular dados do nosso banco. À cada acesso ao aplicativo, este método será acessado, e com ele criaremos uma conexão e atualizaremos os dados do banco (deletando os registros antigos, criando as tabelas novamente, e populando-as).
  • criaTabela() → Neste método passamos um SQL como argumento, que criará as tabelas que utilizaremos em nosso aplicativo.

Agora seguiremos a classe BancoDaoImpl.java mostrando como operações de CRUD são realizadas, através da interação de cursores e métodos de acesso direito ao banco de dados, como query() e execSQL().

Na sequência da nossa classe, temos os métodos: populaTabelaPergunta(), pesquisaPergunta(), pesquisaResposta(), insereResposta(), listarPerguntas(), listarRespostas() e fechaConexao(). Relembrando as operações CRUD: os métodos criaTabela() e populaTabelaPergunta() implementam o “C” do CRUD (Create); os métodos pesquisaPergunta(), pesquisaResposta() e listarPerguntas() implementando o “R” (Read); nenhum método implementan o “U” (Update); e nenhum método implementando o “D” do CRUD (Delete). O método fechaConexao() não é um método de CRUD, mas sim um método que gerencia o acesso ao banco de dados.

Na figura abaixo, não mostraremos todos estes métodos. Mostraremos apenas um exemplo da operação “Create” e um exemplo da operação “Read”. Algo bem básico.



Acima temos o método insereResposta() (implementando a operação “Create”) e os métodos pesquisaPergunta() e listarPerguntas() (implementando a operação “Read”). Vamos à eles:


  • O método pesquisaPergunta()  recebe como parâmetro o id da pergunta à ser pesquisada, e retorna um Cursor. Neste método, mais uma vez, o primeiro comando executado é a abertura do banco de dados através do método context.openOrCreateDatabase(). Após isto, o comando SQL foi executado através do método query(). O construtor do método query() é: public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit). No nosso método pesquisaPergunta() temos: query(true, "pergunta", colunas, where, null, null, null, null, null). Desta forma:
    • O parâmetro distinct recebeu true. Logo, se existir mais de um registro repetido na tabela, mais de um registro será retornado.
    • O parâmetro table recebeu “pergunta”. Logo, passamos à query a tabela Pergunta.
    • O argumento columns recebeu colunas. Como podemos ver na imagem acima: String[] colunas = {"idPergunta", "idDisciplina", "pergunta", "respostaCorreta"};. Logo, estamos passando à query todas as colunas que serão retornadas pelo banco de dados.
    • O parâmetro selection recebeu where. Na imagem acima vemos que String where = "idPergunta = " + idPergunta;. Assim, estamos passando à query o critério de seleção para buscar dados na tabela Pergunta.
    • Os demais 5 parâmetros são null pois já temos tudo que precisamos para nossa query retornar os dados desejados.
  • O método insereResposta() utiliza o método execSQL() para realizar à operação SQL. O que muda neste método em relação ao método criaTabela() (muito similar ao insereResposta()) é que neste método a variável sql montada utilizando o parâmetros do nosso método, a fim de insermos apenas uma resposta no banco de dados (ou seja, inserir a resposta passando como parâmetro).
  • método listarPerguntas() também utiliza o método query(). Os 3 primeiros parâmetros deste método são análogos aos do método pesquisaPergunta(). Porém, o 4º parâmetro é diferente. O parâmetro selection, neste caso, é nulo. Ou seja, todos os registros serão retornados. Também o 8º método é diferente. Neste caso, o parâmetros orderBy recebe o valor “idPergunta”. Logo, todas as perguntas retornadas pelo banco de dados serão ordenadas pelos seus id.


A maneira com que os cursores são lidos será especificada mais a frente.

Por fim, temos o método fechaConexao().



Este método finaliza a conexão com o banco de dados SQLite. É IMPORTANTÍSSIMO que este método seja chamado, senão poderemos ter casos de estouro de memória utilizada.

Por fim, falaremos do pacote view. Neste pacote temos todas as Activity’s (telas) que serão utilizadas pelo aplicativo. Serão 4 no total: LoginActivity.java, TelaInicial.java, QuizzGeografia.java e PontuacaoFinal.java.

Então, por qual tela começamos? Para isso, precisamos dar uma olhada no arquivo AndroidManifest.xml.



Assim, podemos concluir que a primeira tela à ser aberta por nosso aplicativo será a tela LoginActivity.java. Esta tela será explicada em detalhes, abaixo. Ela não contém explicações sobre o conteúdo deste post, mas ela será destrinchada por se caracterizar como uma classe útil para fazermos uma revisão de tudo que foi visto no Blog até agora.

Logo abaixo, temos o Javadoc da nossa classe. O Javadoc é a documentação que identifica uma classe (e também métodos, variáveis, etc, como mostraremos mais adiante neste post).




Agora, temos a definição da nossa classe como uma Activity. Note que ela implementa um ClickListener, e que possui as variáveis mEdtUsuario e mBtnIniciar.

Repare também que estas variáveis (que são atributos de classe) começam com uma letra “m”. Por que? Porque em Java temos padrões de nomeação de variáveis. São eles:


  • VariávelTODA variável em Java deve começam em letras minúsculas, e caso seu nome possua mais de um termo ou palavra, este deve possui apenas uma letra maiúscula: a primeira letra do termo/palavra. Exemplo: String umaString;
  • Atributo de classe → Coloca-se um prefixo com a letra “m”. Exemplo: private EditText mEdtUsuario;
  • ConstanteToda constante em Java, além de ser definida como um final (variável com valor imutável), deve ser maiúscula. Exemplo: public static final String CONSTANTE = “constante”;
  • EstáticosUma variável estática é uma variável que é mantida na memória ao longo de todo o tempo de vida do programa. E ao contrário de uma constante, ela é mutável. Exemplo: public static String sNomeDoPrograma = “nome_do_programa”;




Tais padrões se extendem, também, para o desenvolvimento Android.



Continuando a explicação da nossa classe, temos os eventos onCreate() e onDestroy(). Neles temos comandos de log e de criação da tela da nossa LoginActivity.java (através do comando setContentView() do evento onCreate()).



Em sequência, temos mais eventos de uma classe Activity. De mais interessante, podemos enaltecer os métodos setResult(RESULT_CANCELED) e finish(). O primeiro método se relaciona com o que foi ensinado neste post do Blog; e o segundo sai da tela atual (e que por ser a primeira da nossa aplicação, corresponde também à saída da aplicação).



Já na figura abaixo, temos um código mais interessante. No evento onResume() (que é chamado sempre que o contexto da aplicação entra em uma tela, seja pela primeira vez, ou seja retornando à ela), temos, além dos comando de log, a inicialização do listener do botão. Mas apenas isso. Onde teremos então a ação que tal botão realizará?




A ação do botão é mostrada abaixo, no evento onClick(). Nela verificamos se o login do usuário não é nulo. Se não for, o contexto da aplicação é desviado para a tela TelaInicial.java, e também o nome do usuário é passado para esta tela como um extra da Intent chamada.



Por fim, na tela LoginActivity.java, temos um método (com seu devido Javadoc) que obtém o nome da classe em que o contexto da aplicação se encontra. Esse método foi utilizado em nossa classe pelos comandos de log.



Pudemos notar que este login é extremamente simples. Ele não possui senha e quase nenhuma validação de campos. Isso foi feito propositalmente, para facilitar na didática e apresentação de conceitos iniciais em programação Android.

Agora que já reforçamos bastante muitos conceitos ensinados nesta apostila (Ciclo de Vida de uma Activity, Conceitos de Interface, Intent, dentre outros), vamos destrinchar a tela QuizzGeografia.java. Por que esta tela, e não a tela TelaInicial.java, que é a próxima tela que a aplicação acessará? Porque a tela TelaInicial.java possui uma estrutura parecida com a tela LoginActivity.java, e nosso foco agora será explicar a relação do pacote view com os pacotes impl e bean (o que é feito na classe QuizzGeografia.java).

Abaixo temos a classe QuizzGeografia.java. Para entendê-la bem, podemos dar uma conferida nas variáveis que esta classe possui.




Podemos perceber que existem variáveis utilizadas na manipulação de bancos de dados, e também variáveis de componentes gráficos da classe. Mais adiante, temos os eventos de ciclo de vida da tela.






Dentre eles, o mais importante é o onResume().




Repare que é neste evento que o método mDb.criaTabelas() é chamado. Ou seja, sempre que esta tela for acessada, as tabelas do banco de dados serão geradas. Temos também o método obtemPergunta(), que indiretamente faz acesso ao banco de dados, como será mostrado mais adiante.

Seguindo nossa tela, temos a definição de alguns métodos usados ao longo dela. O método getClassName() obtém o caminho da classe nos pacotes do aplicativo, e o método tituloUsuario() apenas atualiza o nome do usuário na tela.




Agora temos o método obtemPergunta(). Ele utiliza o método retornaPergunta(), que de forma direta obtém as perguntas do banco de dados. Como isto é feito será mostrado mais adiante.



Agora temos o método acaoBotao(), que encapsula o que será realizado pelo botão de resposta. Podemos notar que é chamado o método insereResposta(), que insere no banco a resposta que o usuário escolheu (Sim ou Não), e que logo após disso a conexão com o banco de dados é fechada. Ela é fechada pois mantê-la aberta é uma má prática, pois manter a conexão aberta consome recursos do nosso aplicativo.

Repare também que o if deste método controla se será mostrada na tela uma das 10 perguntas, ou se sairemos da tela de Quizz de Geografia (tal ação é executada no else deste método).




Como podemos perceber acima, foi chamado o método finalizaTela(). Abaixo temos sua implementação. Nele, chamamos o método que calcula a pontuação do Quizz, desviamos o fluxo do aplicativo para a tela PontuacaoFinal.java, e também fechamos a conexão com o banco de dados.





O método que calcula a pontuação é mostrado abaixo.



Como mencionado no início deste post, a leitura de dados de uma tabela de um banco de dados é feita através da classe Cursor. No método acima podemos perceber que os valores da tabela Pergunta são lidos pelo método listarPerguntas(), e também como colocamos tais valores em variáveis da nossa classe (que neste método são os arrays Integer[] corretas e Integer[] usuarios).

Ou seja, tudo que precisamos fazer é percorrer todos os elementos de um Cursor através de um comando for each. Desta forma podemos comparar as respostas corretas com as respostas dadas pelo usuário, e descobrir quantas respostas o usuário acertou.

Por fim, vamos aos métodos que lêem do banco de dados a Pergunta e a Resposta de cada uma das 10 questões do nosso Quizz.



Podemos notar que mais uma vez foi utilizada a classe Cursor. No método retornaPergunta(), cada coluna da tabela Pergunta é lida e inserida em algum atributo do tipo Pergunta. O mesmo é feito no método retornaResposta().

Não há muito segredo: quando precisamos acessar nosso banco de dados, tudo que precisamos fazer é interagir o pacote view com o pacote impl. Isto é feito chamando a classe BancoDaoImpl, que na tela QuizzGeografia.java está armazenada na memória através da variável mDb.

E isso é tudo. O exemplo demonstrado neste post foi bem simples e básico (se comparado aos exemplos que serão mostrados nos próximos post do Blog). Mas o conceito básico não muda: quando formos nosso banco de dados, tudo que precisamos fazer é interagir um pacote view com um pacote impl.

O que mudará nos posts subsequentes deste Blog é a maneira como os dados são obtidos do banco de dados, o que pode ser realizado de maneira muito menos trabalhosa.


-----

E aqui terminamos mais um tópico do blog.

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