32
junho 2015

The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015

Page 2: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015

Page 3: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 03

Índice

Editorial

04

12

Autor: Hamden Vogel

05

20

Autor: Thiago C. Montebugnoli

Autor: Luciano Pimenta

Asp.Net - Trabalhando com jQuery 2.x

Manipulação de arquivos: Otimizações em Procura de Arquivos e Conteúdos (nova estrutura TWin32FindDataA e algoritmo Damerau–Levenshtein)

SQLite - Banco de dados no Android

Page 4: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201504

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Prezado leitor,

É com muita satisfação que preparamos este mês uma coleção de artigos compostos dos mais diversos tipos assuntos. Nosso colunista Luciano Pimenta redigiu o artigo “SQLite – Banco de dados no Android”, ensinando todas as técnicas para trabalhar com este mecanismo para dispositivos móveis. Artigo recomendado tanto para os iniciantes quanto para os que desejam aprimorar seus conhecimentos sobre esta tecnologia. Já nosso colaborador mensal Hamden Vogel, conti-nua abordando assuntos sobre manipulação de arquivos utilizando como ferramenta de desenvolvimento o Delphi. Neste mês ele faz o uso da estrutura “Twin32FindData” junto com o algoritmo Damerau Levenshtein, tendo como meta aumentar a eficiência e a performance programando Multithread. Para finalizar a revista, eu escrevo sobre um tema muito comentado em todos os tipos de linguagens Web, as bibliotecas Javascript JQuery. Apresento a sua versão 2.1.4, explicando desde sua aquisição e instalação seguindo de exemplos práticos utili-zando os denominados “Selectors” e os “Events”.

Desejo a todos uma ótima leitura, até o mês que vem!

Abraços

Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP 18.707-150

Informações e Suporte: (14) 3732-1529

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected] Cadastro: theclub_cadastro

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club 2013

Diretor TécnicoMarcos César Silva

DiagramaçãoVitor M. Rodrigues

DesignVitor M. Rodrigues

RevisãoDenise Blair

ColunistasHamden Vogel

Jeferson Silva de LimaLuciano Pimenta

Marlon Aparecido Branco ValentinoThiago Cavalheiro Montebugnoli

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais.

Editorial

Page 5: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 05

Neste mês irei abordar um assunto muito utilizado em pra-ticamente toda aplicação Web, o uso do JQuery 2.x. Neste artigo irei ressaltar algumas informações específicas sobre esta nova versão, seguindo de como devemos adquiri-la e instalá-la manualmente e automaticamente em uma solução

com a ferramente de desenvolvimento da Microsoft, o Microsoft Visual Studio 2013. Explicarei também conceitos e informações de Seletores (“Selectors”) e os Eventos (“Events”).

Conceito

Tendo como referência o site oficial, podemos afirmar que jQuery é uma biblioteca de JavaScript com funcionalidades rápidas, pequena e rica em re-cursos. Possui características marcantes como: manipulação de HTML, uso de Eventos, implementação com o Ajax, entre outros, se tornando muito simples com uma API de fácil aprendizado e que funciona através de uma multiplicidade de navegadores. Com esta biblioteca, a tarefa de adicionar interatividade a uma página web se torna muito mais fácil e prática.

Informações importantes sobre a versão jQuery 2.x

• Em relação a versão anterior (JQuery 1.x), esta segunda foi de-senvolvida para a Web moderna, abandonando o suporte aos browsers mais antigos (Internet Explorer 6/7/8).

• Possibilidade de personalização da biblioteca, tendo inúmeros módulos diferentes, como por exemplo o ajax, ajax/xhr, ajax/script, css, di-mensions, effects, wrap, etc ... (Não irei entrar em detalhes sobre os mesmos).

• O JQuery 2.x é 12% mais leve do que a versão anterior, justamente pelo fato da remoção de patches de compatibilidade do Internet Explorer (como foi comentado no primeiro tópico).

Baixando e Instalando

Para adquirir a biblioteca jQuery será necessário entrar no site oficial (https://jquery.com/) e clicar no item de menu “Download”, Ver Imagem 01.

Figura 01: Site Oficial.

Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x.

Para cada versão possuímos quatro links, sendo:

Download the compressedCópias comprimidas de arquivos jQuery, economia de espaço e aumento

de desempenho na produção.Download the uncompressedCópias não comprimidas de arquivos jQuery, sendo melhor utilizado

durante o desenvolvimento ou a depuração. Download the map fileArquivo para uso quando a depuração utilizar um arquivo compactado.

Este arquivo não é necessário para que os usuários executem jQuery, só auxilia a depuração do desenvolvedor.

Release notesInformações sobre os recentes lançamentos e atualizações.

Podemos realizar o download do jQuery 2.x, versão compactada. (A versão atual até a data deste artigo é a “jQuery 2.1.4”). Para isto clique com o botão direito sobre o link escolhendo “Salvar Link como...” Crie uma pasta “jquery”

Asp.Net – Trabalhando com JQuery 2.x

Page 6: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201506

para futuras implementações em seu projeto.

Confira os detalhes na Figura 02

Figura 02: Download jQuery 2.x, versão comprimida.

O arquivo baixado é de extensão “js”, com tamanho de aproximadamente 83kb. Ver Imagem 03.

Figura 03: Biblioteca jQuery 2.1.4.

Recomendo realizar uma leitura no próprio site, pois o mesmo contém todas as informações e dicas referentes à esta biblioteca.

Instalação Automática

Os passos descritos acima demonstra como devemos proceder para realizar a instalação da biblioteca jQuery de uma forma manual. Poderíamos nos poupar deste trabalho e instalá-la de uma outra forma no Microsoft Visual Studio através do “Nuget Package Manager”, clicando no item de menu “Tools/Manage Nuget Package/Manage Nuget Package for Solutions...”. Pesquise por jQuery, Ver Figura 04.

Figura 04: Manage Nuget Packages.

Na região superior direita podemos conferir algumas informações como Nome do fabricante, versão, ultima publicação, descrição, entre outros dados. Basta clicarmos no botão “Install” para obtermos o jQuery instalado em nosso

projeto.

Projeto Base

Estarei utilizando o Microsoft Visual Studio 2013 para criar os exemplos de utilização do jQuery. Para isto inicie um projeto do zero clicando no menu File/New Web Site. Para fins didáticos recomendo escolher a opção “Asp.Net Empty Web Site”, para criar um projeto com apenas os itens excenciais.

Figura 05: Criando um novo projeto Asp.Net.

Poderemos concentrar os nossos exemplos a partir de um Web Form, para isto clicando com o botão direito sobre a “Solution” o adicione navegando até a opção “Add/New Item...” Neste caso uma sugestão de nome como por exemplo “FrmjQuery”. Ver Imagem 06.

Figura 06: Criando um Web Form.

Como foi descrito no tópico anterior, deveremos disponibilizar a Biblioteca jQuery dentro da pasta deste projeto, como ilustra a imagem 07.

Figura 07: Padrão de pastas do projeto de exemplo.

O nosso Projeto deverá estar conforme Imagem 08.

Page 7: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 07

Figura 08: Projeto de Exemplo.

Declaração e Sintaxe

O primeiro exemplo servirá de base para o restante do artigo, utilizamos a função “Hide()” para ocultar todos os dados contidos nas tags <p> (“Selectors” e “Events” serão exemplificados nos próximos tópicos). Para isto, clique sobre o “FrmjQuery.aspx” e em Source adicione o código contido na Listagem abaixo.

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”FrmjQuery.aspx.cs” Inherits=”FrmjQuery” %>

<!DOCTYPE html>

<html xmlns=”http://www.w3.org/1999/xhtml”><head runat=”server”> <title> Exemplos jQuery 2.x</title> <script src=”jquery/jquery-2.1.4.min.js”></script>

<script> $(document).ready(function () { $(“button”).click(function () { $(“p”).hide(); }); }); </script>

A parte que nos interessa e a mais importante deste Web Form é a inclusão do arquivo js (JQuery), o mesmo sendo responsável pelo código da biblioteca jQuery. Esta inclusão deverá sempre estar localizada dentro da TAG <Head> junto com a função “Hide()”.

</head><body> <div> <h2>Este é o Título</h2>

<p>Tudo o que está escrito aqui será ocultado!</p> <p>The Club - Aqui também será ocultado.</p> <button>Ocultar Linhas</button> </div></body></html>

Observe como usamos o identificador da <DIV> para chamar o método Hide(), todos os valores contidos entre as Tags <p> serão ocultados ao clicarmos no botão “Ocultar Linhas”. Ver Imagem 09 para maiores detalhes.

Figura 09: Exemplo prático.

Após entendermos como funciona a declaração, utilização e sintaxe da biblioteca jQuery, gostaria de apresentar nas próximas páginas outras partes im-portantes como por exemplo os “Selectors” (Seletores) e os “Events” (Eventos).

O que são os “Selectors”?

Os seletores JQuery são de extrema importância na biblioteca jQuery, pois permitem selecionar e manipular elementos HTML. Eles são usados para “Localizar” elementos HTML com base no ID, tipos, classes, atributos, valores de atributos, entre outros. Todos os seletores jQuery deverão começar com o sinal de dólar e parênteses, exemplo: $ ().

1) Element Selector (Seletor por Elemento)

O seletor de elemento jQuery seleciona elementos com base no nome do mesmo. Poderemos selecionar todos os elementos contidos entre a TAG <p> de uma página.

Sintaxe:

$(“p”).hide();

Page 8: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201508

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script>

<script>$(document).ready(function(){ $(“button”).click(function(){ $(“p”).hide(); });});</script>

</head><body><h2>Este é o Título</h2><p>Tudo que está aqui será ocultado!</p><button>Ocultar</button></body></html>

Quando um usuário clica em um botão , todos os elementos <p> ficarão ocultos. (Vide exemplo anterior para maiores detalhes)

2) #id Selector (Seletor por #id)

O seletor #id jQuery usa o atributo id de uma tag HTML para encontrar o elemento específico. Um id deve ser único dentro de uma página , por isto deveremos usar o seletor #id quando desejamos

encontrar um único elemento. Quando um usuário clica em um botão , o elemento com id = “teste” será ocultado, veja a sintaxe e o exemplo a seguir.

Sintaxe:

$(“#test”).hide();

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script>

<script>$(document).ready(function(){ $(“button”).click(function(){ $(“#test”).hide(); });});</script>

</head><body>

<h2>Este é o Título</h2><p>The Club.</p><p id=”test”> Tudo que está aqui será ocultado!</p><button>Ocultar</button></body></html>

3) Class Selector (Seletor por Classe)

O seletor de classe jQuery encontra elementos de acordo com uma classe específica. Quando um usuário clica em um botão , os elementos com class = “teste” será escondido.

Sintaxe:

$ (“.test”)

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“button”).click(function(){ $(“.test”).hide(); });});</script></head><body>

<h2 class=”test”>Este é o Título</h2>

<p class=”test”> Tudo que está aqui será ocultado!</p><button>Ocultar</button></body>

4) Outros Seletores importantes:

Possuímos inúmeros seletores na biblioteca jQuery, na sequência gostaria de apresentá-los com a sintaxe e uma leve descrição dos mesmos.

$( “*”) : Seleciona todos os elementos.$(this): Seleciona o elemento HTML atuais.$(“p.intro”): Seleciona todos os elementos <p> com class = “ intro”.$(“p:first”): Seleciona o primeiro elemento <p> contido entre a tag.$(“ul li : first”): Seleciona o primeiro elemento <li> da primeira <ul>.$(“ul li : first-child”): Seleciona o primeiro elemento <li> de cada <ul>.$(“[ href ]” ): Seleciona todos os elementos com um atributo href.$(“a[target = ‘ _ blank ‘]”): Seleciona todos os elementos <a> com um

valor igual a “_blank”.$(“a [target! = ‘ _ blank ‘]”): Seleciona todos os elementos <a> com um

Page 9: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 09

alvo valor diferente de “ _blank “.$(“:button”): Seleciona todos os elementos <button> e <input> elementos

de type = “button”.$(“tr: even”): Seleciona todos os elementos even <tr >.$(“tr : odd”): Seleciona todos os elementos odd <tr>.

O que são os “Events”?

Pode-se dizer que os eventos são um dos elementos mais importantes no desenvolvimento de aplicações web, são ações ocorridas na página, à medida que o usuário a utiliza. Um evento representa o exato momento em que algo acontece. Um bom exemplo disto seria o movimento do mouse sobre um elemento, selecionando o radio button ou até mesmo o ato de clicar sobre algum lugar.

Abaixo temos os principais tipos de eventos, sendo:

Eventos do Mouse: click, dblclick, mouseenter, mouseleave.

Eventos do Teclado: keypress, keydown, keyup.

Para atribuir um evento de clique para todos os parágrafos em uma página, podemos fazer da seguinte maneira:

$(“p”).click();

Após definir o evento, deveremos programar o que acontecerá quando este evento é acionado. Exemplo:

$(“p”).click(function(){ // Ações });

1) Mouse events (Eventos do Mouse)

Click()

Esta função é executada quando o usuário clica em algum elemento específico HTML. No exemplo a seguir iremos ocultar o elemento <p> ao ser disparado o evento click().

Sintaxe:

$(“p”).click(function(){ $(this).hide();});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script>

<script>$(document).ready(function(){ $(“p”).click(function(){ $(this).hide(); });});</script></head><body>

<p>Se clicar aqui serei ocultado.</p><p>Aqui também!</p>

</body></html>

Dblclick()

Esta função será executada quando o usuário clica duas vezes no elemento HTML.

Sintaxe:

$(“p”).dblclick(function(){ $(this).hide();});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“p”).dblclick(function(){ $(this).hide(); });});</script></head><body>

<p>Ao realizar um duplo clique irei ser ocultado.</p><p>Eu também serei!</p>

</body></html>

Mouseenter()

Já este evento será executado quando o mouse entrar em um elemento HTML.

Page 10: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201510

Sintaxe:

$(“#p1”).mouseenter(function(){ alert(“Você entrou na TAG p1!”);});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“#p1”).mouseenter(function(){ alert(“Você entrou na TAG p1!”); });});</script></head><body>

<p id=”p1”>Entre neste parágrafo!!</p>

</body></html>

Mouseleave()

A função é executada quando o ponteiro do mouse deixa o elemento HTML.

Sintaxe:

$(“#p1”).mouseleave(function(){ alert(“Você está deixando este elemento HTML!”);});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“#p1”).

mouseleave(function(){ alert(“Você está deixando este elemento HTML!”); });});</script></head><body>

<p id=”p1”>Saia deste Parágrafo!</p>

</body></html>

2) Keyboard events (Eventos do Teclado)

Keypress() Este evento é disparado quando ocorre alguma ação do teclado. No exem-

plo abaixo temos uma situação que o usuário digita algo e logo em seguida disparamos o evento Keypress para contar o número de caracteres digitados.

Sintaxe:

$(“input”).keypress(function(){ $(“span”).text(i += 1);});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>i = 0;$(document).ready(function(){ $(“input”).keypress(function(){ $(“span”).text(i += 1); });});</script></head><body>

Entre com seu Nome: <input type=”text”>

<p>Quantidade de Caracteres: <span>0</span></p>

</body>

Page 11: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 11

</html>

Keydown()

Este evento é identico ao anterior, só que o mesmo é disparado quando pressionamos a tecla, descendo o dedo na tecla. Neste caso iremos alterar a cor de fundo do componente para amarelo ao executar o evento KeyDown.

Sintaxe:

$(“input”).keydown(function(){ $(“input”).css(“background-color”, “yellow”);});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“input”).keydown(function(){ $(“input”).css(“background-color”, “yellow”); });});</script></head><body>

Entre com o Nome: <input type=”text”></body></html>

Keyup()

Evento que ocorre após o KeyDown, ou seja, depois que a tecla é pressio-nada. No exemplo abaixo iremos alterar a cor de fundo do componente para rosa ao executar o evento KeyUp.

Sintaxe:

$(“input”).keyup(function(){ $(“input”).css(“background-color”, “pink”);});

Exemplo:

<!DOCTYPE html><html><head><script src=”jquery/jquery-2.1.4.min.js”></script><script>$(document).ready(function(){ $(“input”).keyup(function(){ $(“input”).css(“background-color”, “pink”); });});</script></head><body>

Entre com o nome: <input type=”text”>

</body></html>

Conclusões

Neste artigo pude apresentar algumas informações importantes para quem pretende trabalhar com a biblioteca jQuery. Abordei algumas informa-ções sobre a última versão 2.x, dicas de instalação manual e automática pelo Microsoft Visual Studio, declaração e sintaxe com base nos Seletores (Selectors) e nos Eventos (Events).

Fica aí a dica, um abraço e até o mês que vem!

Referênciashttps://jquery.com/download/

[email protected]

Thiago Cavalheiro Montebugnoliadora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de Botucatu

– SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

Sobre o autor

Page 12: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201512

Procurar arquivos sempre foi uma tarefa não muito rápida em Delphi, dependendo dos parâmetros de filtro utilizados, sofisticadamente por máscaras para cada tipo de arquivo, algoritmos de pesquisa, pesquisa por subpastas, obtenção do número da linha onde a procura foi localizada, etc; a implemen-tação de tais requisitos nem sempre foi uma tarefa tão trivial assim, exigindo horas de esforço consideráveis para a satisfação de todos esses requisitos de forma eficiente.

Imagine uma procura com métodos avançados – o usuário espera por uma notificação do programa sobre os resultados esperados – e de repente o programa “trava” devido à demora acentuada da função de pesquisa recur-siva, diretório por diretório, comparando todos os arquivos de modo texto e reportando se a procura foi encontrada com sucesso ou não – se não for implementada adequadamente pode ser um mau sinal justamente por não funcionar direito e falhar nesta missão de encontrar as “strings” dentro deste diretório desejado.

Portanto, a solução é desenvolver algo que chama a atenção da eficiência – programação multithread – e algoritmos flexíveis de comparação de carac-teres, seja Unicode ou não, utilizando arrays de caracteres (array[AnsiChar] of AnsiChar) percorrendo estas estruturas com emprego de ponteiros para “varrer” todos os apontamentos do tipo AnsiChar alocados – aí sim, está algo eficiente e prático!

Figura 01 – Modo tradicional de pesquisa de arquivos, utilizando o record TSear-

chRec juntamente com a estrutura TWin32FindData (Windows).

Método tradicional – Utilizando TSearchRec

A estrutura TSearchRec é muito utilizada até hoje no mundo de desen-volvimento em Delphi, pelo fato também de não haver outra escolha natural, desde que se criem as alternativas de melhor resposta e eficiência – e é o propósito deste artigo – e vamos demonstrar estas alternativas inteligentes de pesquisa de arquivos e conteúdos logo adiante.

Um trecho do fonte responsável pela manipulação desta estrutura seria o emprego dos métodos FindFirst/FindNext – que levam a TWin32FindData do Windows e trazem os resultados desejados.

Estrutura TSearchRec

Atributo DescriçãoTime Armazena a Data/Hora da modificação do arquivo.

Size Tamanho em bytes do arquivo encontrado.

Attr Atributos do arquivo, para controlar a pesquisa dos arquivos. São eles: FaAnyFile (qualquer arquivo), Fa-Directory (diretórios), FaReadOnly (arquivos somente leitura), faHidden (arquivos ocultos), faArchive (arquivos em geral), faSysFile (arquivos de sistema) e faVolumeID (arquivos do tipo volume Id).

Name Nome do arquivo encontrado (sem nome do caminho do diretório de onde ele reside).

Exclude Attr Atributos para excluir da pesquisa.

FindHandle Handle interno.

FindData Armazena informações sobre a data de criação do ar-quivo, bem como a data do seu último acesso e os seus nomes do tipo short e long (abreviado e normal).

Esses são os atributos utilizados no dia-a-dia de um desenvolvedor Delphi para obter uma lista de arquivos em um diretório, por exemplo. Vamos a uma

Manipulação de arquivos: Otimizações em Procura de Arquivos e Conteúdos (nova estrutura TWin32FindDataA e algoritmo Damerau–Levenshtein)

Page 13: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 13

ilustração prática:

Demonstração da utilização dos atributos de um arquivo – exemplo:

Demonstração da utilização dos atributos de um arquivo. Observe no código-fonte abaixo os tipos de atributos mapeados que devem ser retornados em uma lista de diretórios/arquivos a serem procurados em um parâmetro de busca em FindFirst. Estes atributos de arquivos estão destacados em negrito abaixo:

1. R => ReadOnly (faReadOnly);2. H => Hidden (faHidden);3. S => System (faSysFile);4. D => Directory (faDirectory);5. A => Archive (faArchive);6. V => Volume Id (faVolumeID).

{$APPTYPE CONSOLE}program test1; uses sysutils; { test program #1 for FindFirst/FindNext FAQ by Glenn9999, demonstrates testing for attributes }

procedure writeattr(inattr: longint); { tests file attributes and writes out a corresponding letter for it } begin { list of file attributes } if (inattr and faReadOnly) = faReadOnly then write(‘R’); if (inattr and faHidden) = faHidden then write(‘H’); if (inattr and faSysFile) = faSysFile then write(‘S’); if (inattr and faVolumeID) = faVolumeID then write(‘V’); if (inattr and faDirectory) = faDirectory then write(‘D’); if (inattr and faArchive) = faArchive then write(‘A’); end;

var

SR: TSearchRec; retcode: integer; begin retcode := FindFirst(‘C:\hamden\papirus\artigos\desenvolvimento\*.*’, faAnyFile, SR); while retcode = 0 do begin write(SR.Name, ‘(‘:30-Length(SR.Name)); writeattr(Sr.Attr); writeln(‘)’); retcode := FindNext(SR); end; FindClose(SR); readln; end.

Figura 02 – Um utilitário para demonstrar os tipos de atributos suportados por um arquivo, definidos em SysUtils e utilizados na estrutura TSearchRec.

Em outro teste de lista (exemplo de listagem de arquivos de instalação do MsWindows) podemos ver a seguinte relação destes atributos abaixo:

AUTOEXEC.BAT (A)BJPrinter (HD)boot.ini (RHSA)CONFIG.SYS (A)Documents and Settings (D)error.log (A)FSC (D)IO.SYS (RHSA)MSDOS.SYS (RHSA)

Page 14: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201514

NTDETECT.COM (RHSA)ntldr (RHSA)pagefile.sys (HSA)Program Files (RD)RECYCLER (HSD)sqmdata00.sqm (HA)sqmnoopt00.sqm (HA)System Volume Information (HSD)WINDOWS (D)

Otimização:

A API do Windows, mais precisamente as dll´s NTDLL.DLL e KERNEL32.DLL são utilizadas no modo tradicional de procura de arquivos em Delphi, quando utilizada a estrutura TSearchRec juntamente com os métodos FindFirst/Find-Next, ocupando grandiosa parte do tempo de execução desta função, custoso para volumes consideráveis de arquivos a serem verificados e listados. Mas o que é bom é que podemos eliminar as chamadas de SysUtils para esta funcio-nalidade (porque esta estrutura TSearchRec invoca ela, que por sua vez invoca o Windows, gastando muito tempo, especialmente se há inúmeros arquivos a serem chamados para verificação). Também se pode constatar que os méto-dos FindFirst e FindNext chamam a API do Windows que não faz a filtragem. Em testes feitos (benchmark -> http://www.tek-tips.com/faqs.cfm?fid=7116) pode-se observar uma implementação alternativa à unit SysUtils. A boa novi-dade é que a performance será extremamente superior ao modo tradicional (informações extraídas do site mencionado acima):

“Another benchmark - five times (15300 files, 1670 folders on WinME) Using Sysutils: 1737ms{ … } Using the Windows variants in the main program: 1509ms”

Vamos abordar a alternativa “Windows variants”, a campeã da veloci-dade neste propósito de filtragem de arquivos. Esta implementação proverá a listagem de arquivos em um dado diretório (ou todos arquivos de uma partição) – contando um a um, podendo listar para a tela ou apenas contar internamente, com alto grau de eficiência devido a eliminação das chamadas a unit SysUtils e lidando diretamente com a unit Windows, trazendo portanto mais praticidade ao resultado final.

{$APPTYPE CONSOLE}{$DEFINE NODEBUG}program Project1; uses windows;

{ test program #7 for FindFirst/FindNext FAQ by Glenn9999, allows for benchmarking of file seeking performance. parses through all directories, optionally writing all the results

change define to DEBUG in order to write the directory paths and names

TWin32FindDataA = record dwFileAttributes: DWORD; ftCreationTime: TFileTime; ftLastAccessTime: TFileTime; ftLastWriteTime: TFileTime; nFileSizeHigh: DWORD; nFileSizeLow: DWORD; dwReserved0: DWORD; dwReserved1: DWORD; cFileName: array[0..MAX_PATH - 1] of AnsiChar; cAlternateFileName: array[0..13] of AnsiChar; end; }

const faDirectory = $00000010; type DWord = Longint;

{ a timing routine } function TimeMS: DWord; stdcall; external ‘winmm.dll’ name ‘timeGetTime’;

procedure listdirectory(indir: string); var SR: TWin32FindData; retcode, FindHandle: integer; begin {$IFDEF DEBUG } writeln(indir); {$ENDIF} FindHandle := Windows.FindFirstFile(PChar(Indir + ‘\*.*’), SR); if FindHandle <> INVALID_HANDLE_VALUE then Retcode := 0 else Retcode := GetLastError; while retcode = 0 do begin {$IFDEF DEBUG } writeln(SR.

Page 15: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 15

cFileName); {$ENDIF} if (SR.dwFileAttributes and FaDirectory) = faDirectory then begin if (String(SR.cFileName) <> ‘.’) and (String(SR.cFileName) <> ‘..’) then ListDirectory(indir + ‘\’ + SR.cFileName); end; if Windows.FindNextFile(FindHandle, SR) then Retcode := 0 else Retcode := GetLastError; end; if FindHandle <> INVALID_HANDLE_VALUE then Windows.FindClose(FindHandle); end;

var STime: Longint; numtimes, i: longint; strDirectory: String; begin Writeln(‘test program #7 for FindFirst/FindNext FAQ by Glenn9999,’); Writeln(‘allows for benchmarking of file seeking performance.’); Writeln(‘parses through all directories, optionally writing all the results.’); Writeln; Writeln; writeln(‘Enter a directory to run:’); Readln(strDirectory); writeln(‘How many times to run: ‘); readln(numtimes); STime := TimeMS; for i := 1 to numtimes do listdirectory(strDirectory); STime := TimeMS - STime; Writeln; Writeln;

writeln(‘Directory: ‘ + strDirectory); write(‘Program completed in ‘, STime, ‘ ms. Press Enter to Exit.’); readln; end.

Figura 03 – Tela do programa “Windows Variants” de implementação alternativa a TSearchRec (mais rápida por ter menos chamadas ao Windows).

Implementando o algoritmo de “Damerau–Levenshtein” para medição entre a distância da equivalência entre duas strings

Sempre há espaço para aperfeiçoar nossas técnicas de pesquisa, seja oti-mizando nosso código bem como versionando uma nova implementação deste algoritmo. O que venho trazer aqui é um algoritmo eficiente para o cálculo da precisão da equivalência entre duas palavras, ou seja, o quão próximo da equi-valência elas são. O que se pode verificar é o grau da precisão, onde 0 é nada equivalente (nada a ver uma palavra com a outra) e 1 é totalmente equivalente (as duas palavras são idênticas). Um exemplo pode ser observado abaixo:

Grau de Equivalência Exemplo1 Palavra 01 e Palavra 010,909090909090909 Palavra 01 e Palavra 0120,6 Palavra 01 e Palavr0,1 Palavra 01 e Psdhfsd2220,4 Palavra 01 e Pala0 Palavra 01 e sss

Este algoritmo representa o número mínimo de operações necessárias para transformar uma string em outra (para realizar esta comparação) onde são compreendidos quatro tipos de operações suportadas, que são Inserção, Exclusão, Substituição e Transposição.

Segue abaixo a relação entre estas operações:

ABC → AXC SubstituiçãoABC → AC Exclusão

Page 16: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201516

ABC → ABXC InserçãoABC ACB → Transposição

Por fim, de acordo com este algoritmo estas quatro operações de edição correspondem a mais de 80% de todos os erros ortográficos humanos encon-trados. E que estas operações citadas acima poderiam corrigir todos estes erros apresentados de ortografia. A original motivação desta implementação é o emprego para as funcionalidades de corretores ortográficos, porém aplica-se em outros campos, como para a medição de variações entre cadeias de DNA na biologia, uma vez que ela também sofre basicamente as mesmas operações de inserção, deleção, transposição e substituição.

O interessante também é que pode detectar erros comuns ou até frau-des como entrada de textos com um caracter transposto ou alterado, por exemplo, em um processo criterioso de verificação; em um banco de dados, enfim, em vários meios onde é necessário uma averiguação mais complexa neste sentido; também pode verificar em um exame onde os candidatos mais acertaram ou chegaram perto de acertar algumas palavras em uma redação, por exemplo; então são inúmeras as possibilidades da implementação deste poderoso algoritmo.

Figura 04 – Tela do programa de exemplo da implementação do algoritmo de Damerau-Levenshtein.

Segue abaixo as funções em Delphi da implementação deste algoritmo (mais adiante segue toda a lógica da implementação):

function DamerauLevenshteinDistance(const Str1, Str2: String): Integer; function StringSimilarityRatio(const Str1, Str2: String; IgnoreCase:

Boolean): Double;

Figura 05 – Outra tela do programa de exemplo da implementação do algoritmo de Damerau-Levenshtein. Note que a segunda palavra de comparação teve um caracter transposto (o “4”) – e o alto grau da distância, quase 1, resultando em uma próxima

dízima periódica – 0,928571 ...

Agora vamos relacionar abaixo o código-fonte responsável por esta im-plementação. Segue abaixo:

unit Unit1;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Button1: TButton; Edit3: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } function DamerauLevenshteinDistance(const Str1, Str2: String): Integer; function StringSimilarityRatio(const Str1, Str2: String; IgnoreCase: Boolean): Double; end;

var Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

function TForm1.DamerauLevenshteinDistance(const Str1, Str2: String): Integer;function Min(const A, B, C: Integer): Integer; begin Result := A;

Page 17: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 17

if B < Result then Result := B; if C < Result then Result := C; end; var LenStr1, LenStr2: Integer; I, J, T, Cost, PrevCost: Integer; pStr1, pStr2, S1, S2: PChar; D: PIntegerArray;begin LenStr1 := Length(Str1); LenStr2 := Length(Str2); // save a bit memory by making the second index points to the shorter string if LenStr1 < LenStr2 then begin T := LenStr1; LenStr1 := LenStr2; LenStr2 := T; pStr1 := PChar(Str2); pStr2 := PChar(Str1); end else begin pStr1 := PChar(Str1); pStr2 := PChar(Str2); end; // bypass leading identical characters while (LenStr2 <> 0) and (pStr1^ = pStr2^) do begin Inc(pStr1); Inc(pStr2); Dec(LenStr1); Dec(LenStr2); end; // bypass trailing identical characters while (LenStr2 <> 0) and ((pStr1 + LenStr1 - 1)^ = (pStr2 + LenStr2 - 1)^) do begin Dec(LenStr1); Dec(LenStr2); end;

// is the shorter string empty? so, the edit distance is length of the longer one

if LenStr2 = 0 then begin Result := LenStr1; Exit; end;

// calculate the edit distance GetMem(D, (LenStr2 + 1) * SizeOf(Integer)); for I := 0 to LenStr2 do D[I] := I; S1 := pStr1; for I := 1 to LenStr1 do begin PrevCost := I - 1; Cost := I; S2 := pStr2; for J := 1 to LenStr2 do begin if (S1^ = S2^) or ((I > 1) and (J > 1) and (S1^ = (S2 - 1)^) and (S2^ = (S1 - 1)^)) then Cost := PrevCost else Cost := 1 + Min(Cost, PrevCost, D[J]); PrevCost := D[J]; D[J] := Cost; Inc(S2); end; Inc(S1); end; Result := D[LenStr2]; FreeMem(D);

end;

function TForm1.StringSimilarityRatio(const Str1, Str2: String; IgnoreCase: Boolean): Double;var MaxLen: Integer; Distance: Integer;begin Result := 1.0; if Length(Str1) > Length(Str2) then MaxLen := Length(Str1) else MaxLen := Length(Str2); if MaxLen <> 0 then begin if IgnoreCase then

Page 18: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201518

Distance := DamerauLevenshteinDistance(LowerCase(Str1), LowerCase(Str2)) else Distance := DamerauLevenshteinDistance(Str1, Str2); Result := Result - (Distance / MaxLen); end;

end;

procedure TForm1.Button1Click(Sender: TObject);begin Edit3.Text := FloatToStr(StringSimilarityRatio(Edit1.Text,Edit2.Text,True));end;

end.

Acima: fonte do programa de exemplo da implementação do algoritmo de Damerau-Levenshtein.

Pesquisando textos utilizando Damerau-Levenshtein em arquivos

Uma forma interessante de se pesquisar textos é a aplicação na prática deste algoritmo Damerau-Levenshtein, onde possamos ver nesta possibilidade um caminho mais flexível de comparação entre duas strings; neste caso em particular a comparação será feita entre o carregamento de um arquivo do modo texto e sua medição da similaridade linha a linha com a palavra a ser pesquisada, conforme o grau de variação entre estas duas comparações (0 – nada encontrado – 1 totalmente idênticos).

Figura 06 – Exemplo de um programa para procura de conteúdo em um arquivo--texto, onde este conteúdo é pesquisado de acordo com a distância da equivalência da comparação de textos baseado no algoritmo de Damerau-Levenshtein.

Pra cada linha será calculado este índice de similaridade utilizando este algoritmo, tomando como parâmetro de pesquisa o grau deste índice que que-remos retornar nesta função. O bom é que podemos informar ao programa o quão idêntico queremos que retorne as informações de cada linha, onde serão exibidas em um objeto do tipo TMemo somente àquelas que satisfazerem estas condições de critério pesquisadas.

Um exemplo da demonstração desta funcionalidade pode ser visualizada abaixo em um trecho deste respectivo código-fonte:

procedure TForm1.Button6Click(Sender: TObject);var File64: TReadOnlyCachedFileStream; PartFileSize: integer; Buffer: array of AnsiChar; i: integer; TempStr: string; sw : TStopWatch; StrmOutput: TMemoryStream; strList: TStringList; strFile: string; sz: int64; const cCRLF = [#13];

begin Memo1.Lines.Clear; Memo1.Lines.BeginUpdate; sw := TStopWatch.Create; DestroyTLineReaderListObjects; FLineReaderList := TLineReaderList.Create; lineCounter := 0; strFile := edtFile.Text; File64 := TReadOnlyCachedFileStream.Create(strFile); try sw.Start; PartFileSize := Self.NumberOfPartsToDivide(Self.GetFileSize(strFile)); File64.Position := 0; sz := File64.Size; strList := TStringList.Create; while (File64.Position < sz) do begin if (sz - File64.Position < PartFileSize) then

Page 19: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 19

PartFileSize := (sz - File64.Position);

StrmOutput := TMemoryStream.Create; try StrmOutput.CopyFrom(File64,PartFileSize); strList.Text := Self.MemoryStreamToString(StrmOutput);

for i := 0 to strList.Count - 1 do begin if (StringSimilarityRatio(strList.Strings[i],edtSearch.Text,True)) >= StrToFloatDef(edtRatio.Text, 0) then Memo1.Lines.Add(‘Encontrado ‘ + strList.Strings[i] + ‘ linha ‘ + IntToStr(lineCounter));

Inc(lineCounter); Application.ProcessMessages; end; finally FreeAndNil(StrmOutput); end; end;

finally Memo1.Lines.EndUpdate; sw.Stop; Label2.Caption := ‘Elapsed ‘ + Self.FormatMillisecondsToDateTime(sw.ElapsedMilliseconds); FreeAndNil(File64); FreeAndNil(strList); FreeAndNil(sw);

Acima: utilizando o algoritmo de Damerau-Levenshtein para pesquisar um arquivo texto.

Conclusão

Vimos algumas técnicas interessantes de procura de conteúdo de strings para arquivos, bem como algumas implementações de melhor performance para procura de arquivos alternativas, substituindo as chamadas tradicionais à estrutura TSearchRec em SysUtils para uma migração à uma nova estrutura

TWin32FindDataA chamando Windows diretamente, trazendo mais eficiência e produtividade e consequentemente menos tempo de espera, consideráveis para um grande volume de arquivos a serem pesquisados recursivamente em subdiretórios, por exemplo. E tal implementação pode ser melhor utili-zada aplicando paralelamente a aplicação deste algoritmo em particular de Damerau-Levenshtein, para uma melhor comparação criteriosa.

A medição da distância métrica entre duas palavras tornam-se um requisito necessário para uma averiguação minuciosa aplicável em muitos campos, e é importante e são vastas as possibilidades de utilização neste sentido, como detecção de entradas inválidas, fraudes, etc; e até no campo da biologia este algoritmo de Damerau-Levenshtein também tem sua utilização para a medi-ção da variação das cadeias de DNA em suas quatro operações de inserção, substituição, exclusão e transposição.

Portanto, vimos nesta primeira parte deste artigo como implementar uma estrutura mais eficiente para procura de arquivos, utilizando esta estru-tura TWin32FindDataA citada acima, e também como implementar com este algoritmo as procuras de conteúdos com arquivos, trazendo um resultado mais preciso de comparações baseado em métricas, contribuindo com mais qualidade e dinamismo baseado em operações de variações de transformação de cadeias de string.

Na próxima parte do artigo veremos como conciliar estas duas técnicas apresentadas aqui acima para uma melhor estratégia em comum, aplicando ambos os estudos para uma melhor implementação mais poderosa para estas funcionalidades, elencadas aqui individualmente.

Bons estudos para o leitor e que tenha bons proveitos neste artigo e que possam gerir boas aplicações e contribuições neste poderoso e produtivo mundo Object Pascal de desenvolvimento!

[email protected]

Hamden VogelAnalista de Sistemas pós-graduado em Engenharia de Software pela

UPIS e Programador Delphi com larga experiência desde 2000, tem de-senvolvido e vendido softwares em Delphi para a África e Estados Unidos, além do mercado nacional. Colaborou com dicas e componentes para sites especializados em Delphi. Também desenvolve em outras linguagens como C/C++, ASP, PHP e .NET.

Sobre o autor

Page 20: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201520

Listagem 1. Layout da tela de cadastro

SQLite é um banco de dados nativo do Android, compacto e não precisa de nenhuma instalação/ configuração no device. Você que está acostumado a usar SQL em gerenciadores de banco de dados robustos (Oracle, SQL Server, MySQL etc), não terá problema nenhum em aprender a usar o SQLite, ele usa SQL ANSII.

Neste artigo veremos como criar o banco de dados e fazermos os principais comandos: select, insert, update e delete.

Criando o projeto

Para usar o SQLite, precisamos criar uma classe que estenda o SQLiteO-penHelper. Vamos criar uma nova aplicação no Android Studio para fazemos os exemplos desse artigo. Abra o Android Studio e crie uma aplicação do tipo Master/detail.

A ideia aqui é ter uma listagem primeiramente, onde podemos adicionar e excluir itens. Através da listagem, vamos acessar os dados de um item e alterar o mesmo. Após criar o projeto, vamos partir para os layouts que teremos.

Crie um novo arquivo XML (layout) e de o nome de “listagem_dados.xml”. Nesse layout apenas coloque um ListView. Crie outro layout chamado “cadastro_dados.xml” e adicione o código da Listagem 1.

<?xml version=”1.0” encoding=”utf-8”?><LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android” android:orientation=”vertical” android:layout_width=”match_parent” android:layout_height=”match_parent”>

SQLiteBanco de dados no Android

<TextView android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”@string/nome” android:id=”@+id/txtNome” android:layout_marginLeft=”30px”/>

<EditText android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/edtNome” android:layout_marginRight=”30px” android:layout_marginLeft=”30px”/>

<TextView android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”@string/dataNascimento” android:id=”@+id/txtNascimento” android:layout_marginLeft=”30px”/>

<EditText

Page 21: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 21

Listagem 2. Layout do template do item da listagem

android:layout_width=”300px” android:layout_height=”wrap_content” android:id=”@+id/edtNascimento” android:layout_marginRight=”30px” android:layout_marginLeft=”30px”/>

<TextView android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:text=”@string/tipo” android:id=”@+id/txtTipo” android:layout_marginLeft=”30px”/>

<Spinner android:layout_width=”match_parent” android:layout_height=”wrap_content” android:id=”@+id/tipo” android:spinnerMode=”dialog” android:layout_marginRight=”30px” android:layout_marginLeft=”30px”/>

</LinearLayout>

As strings, já foram adicionadas no arquivo string.xml. Olhando o preview do arquivo, temos uma tela semelhante a Figura 1.

Veja a Figura 1.

Por fim, vamos criar um layout que será o item da listagem, pois teremos nessa listagem, imagem e dados do cadastro. Crie um novo layout e de o nome de “row_dados.xml”. Veja na Listagem 2 como ficará o layout.

<?xml version=”1.0” encoding=”utf-8”?><RelativeLayout xmlns:android=”http://schemas.

android.com/apk/res/android” android:orientation=”vertical” android:layout_width=”match_parent” android:layout_height=”match_parent” android:paddingBottom=”5dp” android:paddingTop=”5dp”>

<ImageView android:id=”@+id/thumbnail” android:src=”@drawable/ic_launcher” android:layout_width=”50dip” android:layout_height=”50dip” android:scaleType=”fitXY”/>

<TextView android:id=”@+id/nome” android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:textColor=”#040404” android:text=”Nome” android:typeface=”sans” android:textSize=”18dip” android:layout_

Figura 1. Tela de cadastro para o exemplo de SQLite

Page 22: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201522

Listagem 3. Variáveis auxiliares e métodos

toRightOf=”@+id/thumbnail” android:paddingLeft=”7dp”/>

<TextView android:id=”@+id/nascimento” android:layout_width=”fill_parent” android:layout_height=”wrap_content” android:layout_below=”@id/nome” android:textColor=”#343434” android:textSize=”12dip” android:text=”Nascimento” android:layout_marginTop=”1dip” android:layout_toRightOf=”@+id/thumbnail” android:paddingLeft=”7dp”/>

<TextView android:id=”@+id/tipo” android:layout_width=”fill_parent” android:layout_height=”wrap_content” android:layout_below=”@id/nascimento” android:textColor=”#343434” android:textSize=”12dip” android:text=”Tipo” android:layout_marginTop=”1dip” android:layout_toRightOf=”@+id/thumbnail” android:paddingLeft=”7dp”/></RelativeLayout>

Note que temos uma imagem (por padrão a imagem do projeto), que poderia ser o avatar do cliente. Veja no preview (Figura 2), como ficará o item da listagem.

Veja a Figura 2.

Criando o banco de dados

Vamos criar um novo pacote no projeto para adicionar as classes do

banco. Primeiramente, crie uma classe chamada “DataBaseHelper”. Temos que alterar o cabeçalho para:

public class DataBaseHelper extends SQLiteOpenHelper {

}

Temos que declarar o nome e a criação das tabelas que vamos ter no banco. Veja na Listagem 3.

private static String DATABASE_NAME = “sample.db”;private static int DATABASE_VERSION = 1;

public static String TABLE_CLIENTE = “cliente”;

private static String CREATE_CLIENTE = “create table cliente” + “(id integer primary key, “ + “sNmCliente text not null, “ + “tDtNascimento date not null, “ + “nidTipo int not null);”;

Note que criamos constantes para conter o nome e versão do banco, nome das tabelas e o SQL para a criação da tabela. Agora precisamos sobscrever os métodos da classe para poder criar as tabelas.

Veja na Listagem 4 os métodos que devemos implementar

Figura 2. Item da listagem

Page 23: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 23

Listagem 4. Métodos para criar tabelas e banco

Listagem 5. Classe Model para a tabela cliente

Listagem 6. Classe responsável por manipular os dados

public DataBaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION);}

@Overridepublic void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_CLIENTE);}

@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(“DROP TABLE IF EXISTS “ + TABLE_CLIENTE); onCreate(db);}

O construtor chama o método da classe pai, passando como parâmetros o nome do banco e a sua versão. O OnCreate, é onde vamos criar a as tabelas. O onUpgrade, serve para fazermos as modificações necessárias quando preci-samos alterar a estrutura das tabelas da aplicação, que já esta em produção.

No método, temos dois parâmetros, referente à versão anterior e a nova versão do banco de dados. Assim, podemos verificar, em qual versão do banco estamos e executar o código de atualização (adicionar ou remover colunas, por exemplo).

O banco e tabelas estão prontos, na primeira execução do projeto os mesmos serão criados. Vamos criar as classes que vai nos auxiliar na mani-pulação de dados.

Nota: caso você esteja usando um device, saiba que ao desinstalar a app, o banco também é removido. Ao executar novamente (a instalação), o banco voltará zerado.

Primeiro, vamos criar um Model para a tabela cliente. Veja na Listagem 5, a classe ClienteModel.

public class ClienteModel {

private int id; private String sNmCliente; private Date tDtNascimento; private int nIdTipo;}

Vamos usar a facilidade do Android Studio para criar os métodos get e set. Clique com o botão direito do mouse, sobre o nome da classe. No menu, acesse Refactor>Encapsulate Fields. Veremos um editor (Figura 3), para selecionarmos os campos que vamos criar os métodos.

Figura 3. Editor de campos da classe Model_cliente

Clique em Refactor para que os métodos sejam criados. Classe simples, que serve apenas para indicar a estrutura da tabela. Caso queira padronizar o nome dos métodos, fique a vontade, apenas atente para deixar o sufixo get e set.

Vamos criar agora, a classe que será responsável por executar os comandos SQL no banco. Crie uma classe chamado “ClienteDataSource” (salve no diretório da classe do banco) e adicione o código da Listagem 6.

import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import java.sql.Date;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import lasoftwares.samplesqlite.Model.ClienteModel;

public class ClienteDataSource {

private SQLiteDatabase database; private DataBaseHelper dbHelper;

Page 24: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201524

private Context contexto;

public ClienteDataSource(Context context) { dbHelper = new DataBaseHelper(context); contexto = context; }

private void open(){ database = dbHelper.getWritableDatabase(); }

private void close() { dbHelper.close(); }

public boolean Save(ClienteModel cliente) {

try { open();

if (cliente.getId() == 0) Create(cliente); else Update(cliente);

close();

} catch (Exception ex) { return false; } return true; }

private long Create(ClienteModel cliente) {

try {

database.execSQL(“INSERT INTO CLIENTE(sNmCliente,tDtNascimento,nIdTipo) VALUES (‘” + cliente.getNmCliente() + “’,’” + Utils.dateToString(cliente.getDtNascimento()) + “’, ‘” + cliente.getIdTipo() + “’)”);

} catch (Exception ex) {

}

return 0;

}

private long Update(ClienteModel cliente) {

try {

database.execSQL(“UPDATE cliente SET sNmCliente = ‘” + cliente.getNmCliente() + “’, tDtNascimento = ‘” + Utils.dateToString(cliente.getDtNascimento()) + “’, nIdTipo = ‘” + cliente.getIdTipo() + “ where Id = ‘” + cliente.getId() + “’”);

} catch (Exception ex) { }

return 0; }

public int delete(String nCdCliente) {

int id = 0;

try { open();

id = database.delete(“cliente”, “id = ? “, new String[] { nCdCliente });

close(); } catch (Exception ex) { }

return id; }

private ClienteModel cursorToCliente(Cursor cursor) { Model_Cliente cliente = new Model_Cliente(); cliente.setId(cursor.getInt(0)); cliente.setNmCliente(cursor.getString(1)); cliente.setDtNascimento(Utils.stringToDate(cursor, 2));

Page 25: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 25

Listagem 7. Adapter da listagem do cadastro

cliente.setIdTipo(cursor.getInt(3));

return cliente; }

public List<ClienteModel> getAll() {

open();

List<ClienteModel> clientes = new ArrayList<ClienteModel>(); Cursor cursor = database.rawQuery(“select * from cliente”, null);

cursor.moveToFirst(); while (!cursor.isAfterLast()) { ClienteModel cliente = cursorToCliente(cursor); clientes.add(cliente);

cursor.moveToNext(); } cursor.close();

close();

return clientes; }

public ClienteModel getByID (int nCdCliente){

open(); ClienteModel cliente = new ClienteModel (); Cursor cursor = database.rawQuery(“select * from cliente where id=?”, new String[] { String.valueOf(nCdCliente) });

cursor.moveToFirst(); while (!cursor.isAfterLast()) { cliente = cursorToCliente(cursor);

cursor.moveToNext(); } cursor.close();

close();

return cliente; }}

Nessa classe temos todos os métodos (e podemos adicionar mais), para manipular os dados da tabela Cliente. Temos duas variáveis para auxiliar na abertura e escrita de dados no banco e o contexto. Os métodos Open e Close são privados e vamos chamá-los no inicio e final de cada método.

Caso seja necessário, você pode colocar os métodos como public, mas terá sempre que chamá-los antes de cada método (fora da classe). Como podemos ver, no campo relativo a data, temos métodos auxiliares (criei uma Lib para isso), para converter o tipo date em string e string em date.

Agora, vamos implementar o adapter da listagem, pois temos uma listagem customizada, onde teremos imagens. Veja na Listagem 7 o código do Adapter.

import android.app.Activity;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import java.util.ArrayList;import lasoftwares.samplesqlite.Model.ClienteModel;import lasoftwares.samplesqlite.R;

public class ClienteAdapter extends BaseAdapter {

private Activity activity; private ArrayList<ClienteModel> data; private static LayoutInflater inflater = null;

public ClienteAdapter(Activity a, ArrayList<ClienteModel> d) { activity = a; data = d; inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); }

@Override public int getCount() { return data.size(); }

@Override public Object getItem(int position) { return data.get(position); }

Page 26: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201526

Listagem 8. Menu de cadastro da aplicação

@Override public long getItemId(int position) { ClienteModel cliente = data.get(position); return cliente.getId(); }

@Override public View getView(int position, View convertView, ViewGroup parent) {

View vi = convertView;

if (convertView == null) vi = inflater.inflate(R.layout.row_dados, null);

TextView nome = (TextView) vi.findViewById(R.id.nome); TextView nascimento = (TextView) vi.findViewById(R.id.nascimento); TextView tipo = (TextView) vi.findViewById(R.id.tipo);

ClienteModel cliente = data.get(position);

String tipoCliente = (cliente.getIdTipo() == 1 ? “Ótimo” : (cliente.getIdTipo() == 2 ? “Bom” : “Regular”));

nome.setText(cliente.getNmCliente()); nascimento.setText(Utils.dateToString(cliente.getDtNascimento())); tipo.setText(tipoCliente);

return vi; }}

Se você acompanhou os outros artigos, o entendimento é muito fácil, onde recebemos uma lista de clientes e preenchemos os controles de tela. Apenas algo “diferente” fica por conta do tipo do cliente. Como temos um inteiro, verificamos o valor para retornar o texto referente ao tipo.

Menu

Vamos criar o menu que terá um botão para salvar o cliente. Na pasta res, clique com o botão direito e escolha New>Android resource directory. Temos

um editor, semelhante a Figura 4.

Figura 4. Criando um menu

Em Resource type escolha menu e clique em OK. Adicione um Menu Re-source file dentro da pasta, dando o nome de “cadastro” e adicione o código da Listagem 8.

<?xml version=”1.0” encoding=”utf-8”?><menu xmlns:android=”http://schemas.android.com/apk/res/android” xmlns:app=”http://schemas.android.com/apk/res-auto”>

<item android:id=”@+id/action_save” android:title=”@string/salvar” android:icon=”@drawable/ic_salvar” app:showAsAction=”always” /></menu>

O menu possui um nome, texto e ícone (adicionado ao projeto). Queremos que o menu sempre esteja visível, portanto é importante cuidar a propriedade showAsAction. Veja como está a estrutura do projeto na Figura 5.

Veja a Figura 5. Estrutura do projeto

Criando o cadastro

Agora, vamos partir para o cadastro da aplicação. Nele vamos salvar os clientes no banco de dados já criado. Clique com o botão direito no pacote principal e acesse New>Activity>Blank Activity. Vamos modificar o nome da tela, assim como o texto (Figura 6).

Veja a Figura 6. Criando uma nova tela

O editor cria um layout para essa tela, e vamos excluir o mesmo. No On-

Page 27: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 27

Listagem 9. Modificações da tela de cadastro

Listagem 10. Método Save

Create, temos que indicar, qual o layout essa Activity esta vinculada. Vamos modificar também o onCreateOptionsMenu e onOptionsItemSelected para carregar o menu e também saber qual menu foi clicado, respectivamente.

Veja as modificações da tela na Listagem 9 (em negrito).

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.cadastro_dados);}

@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.cadastro, menu); return true;}

@Overridepublic boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId();

if (id == R.id.action_save) { Save(); return true; }

return super.onOptionsItemSelected(item);}

O Save será o responsável por carregar os dados inseridos na tela e salvar no banco. O código está na Listagem 10.

private void Save() { EditText nome = (EditText)findViewById(R.id.edtNome); EditText nascimento = (EditText)findViewById(R.id.edtNascimento); Spinner tipo = (Spinner)findViewById(R.id.tipo);

ClienteDataSource ds = new ClienteDataSource(this); ClienteModel cliente = new ClienteModel();

cliente.setNmCliente(nome.getText().toString()); cliente.setDtNascimento(Utils.stringToDate( nascimento.getText().toString())); cliente.setIdTipo(tipo.getSelectedItemPosition() + 1);

if (nCdCliente > 0) cliente.setId(nCdCliente);

Figura 5. Estrutura do projeto

Figura 6. Criando uma nova tela

Page 28: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201528

Listagem 11. Carregando dados do banco em tela

Listagem 12. Código do OnCreate

Listagem 13. Configurando a listagem de clientes

ds.Save(cliente);

Toast.makeText(this, “Registro salvo com sucesso!”, Toast.LENGTH_LONG).show();

finish();}

No método, pegamos os controles de tela. Após instanciamos a classe do modelo e do DataSource. Preenchemos as propriedades do modelo e chamamos o Save do DataSource. Algumas considerações: nCdCliente é um atributo privado da classe que armazenará o código do cliente, quando esti-vermos editando.

Caso estejamos inserindo, ele será zero. Assim, verificamos seu valor para indicar para o modelo o valor do id. No Save do DataSource, verificamos o valor do id para chamar o Create ou Update. Essa parte é bastante importante. No tipo, atribuímos 1 ao valor do Position, por que ele retornará a partir do zero, e nosso valor começa em 1. Por fim, mostramos uma mensagem para o usuário e fechamos a tela, ele retornará para a tela de listagem de itens.

Teremos outro método que vai carregar os dados nos controles de tela. Veja sua implementação na Listagem 11.

private void LoadData(){

ClienteDataSource ds = new ClienteDataSource(this); ClienteModel cliente = new ClienteModel();

cliente = ds.getByID(nCdCliente);

if (cliente != null && cliente.getId() > 0){ EditText nome = (EditText)findViewById(R.id.edtNome); EditText nascimento = (EditText)findViewById(R.id.edtNascimento); Spinner tipo = (Spinner)findViewById(R.id.tipo);

nome.setText(cliente.getNmCliente()); nascimento.setText(Utils.dateToString(cliente.getDtNascimento())); tipo.setSelection(cliente.getIdTipo() - 1); }}

Bem simples, apenas instanciamos as classes necessárias e preenchemos os controles de tela. Por fim, precisamos receber o código do cliente, caso este-jamos editando um registro. Veja na Listagem 12, as modificações do OnCreate.

...

Spinner tipo = (Spinner) findViewById(R.id.tipo);String[] tipos = new String[3];tipos[0] = “Ótimo”;tipos[1] = “Bom”;tipos[2] = “Regular”;

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, tipos);adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item);tipo.setAdapter(adapter);

if (getIntent().getExtras().containsKey(“nCdCliente”)){ nCdCliente = Integer.valueOf(getIntent().getExtras().get( “nCdCliente”).toString()); LoadData();}

Primeiramente, criamos um array de string, para preencher o Spinner (se-melhante a um ComboBox) com as opções para o campo nIdTipo. Verificamos se temos nosso parâmetro configurado (repassado através da chamada na listagem) para preencher o atributo da classe. Por fim, chamamos o LoadData para preencher os controles de tela.

Listagem do cliente

Finalizamos o cadastro, precisamos apenas configurar a listagem, para car-regar os dados e podermos inserir e excluir registros. No ItemDetailFragment, vamos adicionar o código da Listagem 13 no OnCreateView.

private ClienteAdapter adapter;… setHasOptionsMenu(true);

View rootView = inflater.inflate(R.layout.listagem_dados, container, false);

ListView lista = (ListView)rootView.findViewById(R.id.listView); PreencheLista(lista); lista.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void

Page 29: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 29

Listagem 14. Esperando o retorno da chamada da tela de cadastro

Listagem 15. Configurando o menu de contexto

onItemClick(AdapterView<?> parent, View view, int position, long id) {

//pega o valor do item long nCdCliente = adapter.getItemId(position); //chama a tela de cadastro Intent cadastro = new Intent( getActivity(), ClienteActivity.class); cadastro.putExtra(“nCdCliente”, nCdCliente);

startActivityForResult(cadastro, 1); } });

return rootView;...

private void PreencheLista(ListView lista){ ClienteDataSource ds = new ClienteDataSource(getActivity());

List<ClienteModel> listaClientes = ds.getAll(); adapter = new ClienteAdapter(getActivity(), listaClientes); lista.setAdapter(adapter);

registerForContextMenu(lista);}

Primeiro, carregamos o layout da listagem e em seguida configuramos os dados do banco (DataSource e ListView). Precisamos codificar o evento que o usuário seleciona um item para editar. A chamada é simples, pois pegamos o código do cliente selecionado para enviar ao formulário de cadastro.

A diferença em relação a outros exemplos, é o startActivityForResult, que chama a tela, e temos a possibilidade de ter um “retorno” quando o usuário fechar a tela de cadastro. Assim, podemos atualizar a lista, quando o usuário fechar a tela de cadastro (inserindo ou atualizando um registro).

No código da Listagem 14, temos a definição.

@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);

switch (requestCode) { case 1: ListView lista = (ListView)getActivity().findViewById(R.id.listView); PreencheLista(lista); break; }}

Semelhante ao exemplo do menu do cadastro, configure um menu para a tela de listagem, que vá chamar a tela de cadastro. A única diferença do código do onItemClick do ListView, é que vamos passar “0” no nCdCliente.

Excluindo registro da lista

Como você deve ter notado no código do PreencheLista, temos um método chamado registerForContextMenu. Esse método, vai proporcionar criarmos um menu de contexto, menu que aparece quando você segura um item do ListView.

Vamos adicionar mais métodos para criação e implementação do Excluir, conforme a Listagem 15.

@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

if (v.getId() == R.id.listView) { menu.add(R.string.excluir); }}

@Overridepublic boolean onContextItemSelected(MenuItem item) {

AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

switch (item.getItemId()) { case 0: long id = adapter.getItemId(info.position);

ClienteDataSource ds = new ClienteDataSource(getActivity()); ds.delete(String.valueOf(id));

Page 30: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho201530

ListView lista = (ListView)getActivity().findViewById(R.id.listView); PreencheLista(lista);}

return true;}

No onCreateContextMenu verificamos qual controle está acessando um menu de contexto para criar um item. No onContextItemSelected pegamos as informações do menu e usando o adapter, pegamos o id do registro.

Após, basta chamar o delete do DataSource e atualizar a lista chamando novamente o método.

Usando o cadastro

Após essas configurações, já podemos cadastrar itens no cadastro de clientes. Execute a aplicação, acesse qualquer item da lista do Master/detail. Será aberta a listagem de clientes. Clique no botão de adicionar (Figura 7).

Figura 7. Botão para acessar o cadastro de cliente

Teremos acesso ao cadastro de cliente (Figura 8).

Figura 8. Cadastro de cliente

Preencha os campos e clique no botão na barra. Se não acontecer nenhum erro, a tela será fechada, voltaremos para a listagem atualizada e uma mensa-gem de sucesso será exibida (Figura 9).

Nota: Não fizemos nenhuma validação para os campos obrigatórios, assim como a validação da data. A ideia aqui é mostrar como salvar dados no SQLite. Essa funcionalidade é simples e deixo a cargo do leitor.

Veja a Figura 9.

Após cadastrar alguns itens, podemos testar o excluir. Selecione um item do ListView e segure, será exibido um menu (Figura 10).

Veja a Figura 10. www.lucianopimenta.net

Luciano PimentaLuciano Pimenta (NOVO DOMINIO: www.lucianopimenta.com) é desenvolvedor Delphi/C#

para aplicações Web com ASP.NET, Windows com Win32 e Windows Forms com .NET. Palestrante da 4ª edição da Borland Conference (BorCon) e da 1ª Delphi Conference.

É MVP Embarcadero, grupo de profissionais que ajudam a divulgar o Delphi no mundo. Atualmente é desenvolvedor da SoftDesign fábrica de softwares em Porto Alegre-RS.

Autor de mais de 90 artigos e de mais de 600 vídeos aulas publicadas em revistas e sites especializados, além de treinamentos presenciais e multimídias. É consultor da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de dados.

Sobre o autor

Clique no item e veja que o registro foi excluído e a lista atualizada.

Conclusão

Vimos nesse artigo, como trabalhar com SQLite no Android. Banco simples e de fácil utilização. Quem aprendeu SQL, não terá dificuldade nenhuma em utilizar o SQLite. No próximo artigo, vamos trabalhar com tabelas relacionadas, teremos um cadastro vinculado ao cadastro de clientes. Também veremos algu-mas bibliotecas que usam Mapeamento objeto relacional (ORM) para SQLite.

Um grande abraço a todos e sucesso em seus projetos.

Figura 9. Cadastro criado, listagem atualizada e mensagem de sucesso

Figura 10. Menu de contexto na listagem

Page 31: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015 05

Page 32: The Club - megazine · Na próxima etapa seremos redirecionados para os links das bibliotecas jQuery 1.x e jQuery 2.x. Para cada versão possuímos quatro links, sendo: Download the

junho2015