32
março 2015

The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

  • Upload
    lehanh

  • View
    231

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015

Page 2: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015

Page 3: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 03

21

Índice

Dicas The Club

30

Editorial

04

12

Autor: Hamden Vogel

05

Autor: Marlon Aparecido Branco Valentino

Android - criando uma tela de login

Autor: Thiago C. Montebugnoli

Bootstrap e AngularJS – Tela de carregamento para aplicações web

FastFile - Aplicativo Leitor para Arquivos Grandes

Page 4: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201504

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

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Caro leitor,

Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios. A nossa revista deste mês está mesclada com diversos tipos de assuntos e linguagens. Começando com nosso colunista Hamden Vogel e utilizando o Delphi como ferramenta, ele redigiu o artigo “FastFile 2.0 – Aplicativo Leitor para Arquivos Grandes”. Nesta segunda versão ele implementa novas melhorias em termos de performance dentre outros quesitos interessantes que diz respeito a manipulação de dados. Já o consultor técnico Marlon Aparecido Bran-co Valentino continua com a saga escrevendo artigos relacionados ao Bootstrap. Ele apresenta junto com o framework “AngularJS” uma for-ma alternativa desenvolver uma tela para carregamento de aplicações Web. Para finalizar a revista, escrevi sobre um tema muito usual nas aplicações Android, o artigo: “Android – Criando uma Tela de Login”. Foi desenvolvido um pequeno exemplo junto com algumas classes necessárias para o bom funcionamento, possibilitando adaptações futuras para os sistemas escritos nesta plataforma.

Já nossa seção de Dicas tratamos de um assunto relacionado ao Firebird junto com os componentes Firedac.

Desejo a todos uma boa leitura, um abraço e até o mês que vem!

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 · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 05

1- Introdução

Conforme sua aplicação vai crescendo, logo começam a aparecer os pro-blemas de carregamento, páginas sem estilos, imagens que aparecem pela metade, principalmente se o aplicativo não estiver hospedado em um servidor bom, enfim, uma solução para este problema seria reduzir as requisições do http para o servidor, comprimir seus estilos CSS, suas funções JavaScript, ou até mesmo combinar seus estilos CSS em um arquivo só e fazer o mesmo com as funções JavaScript, caso nenhuma das soluções acima solucione o problema de carregamento, sugiro que acompanhe este artigo onde estarei ensinando a fazer uma tela de pré-carregamento, utilizando a framework do Twitter o Bootstrap e o framwork da Google o AngularJS, que vem crescendo na área de desenvolvimento, principalmente depois do lançamento da versão do Android Lollipop 5.0, onde ele é massivamente utilizado, mas enfim, vamos ao que interessa, a solução para o mau carregamento de sua página.

Imagem 01 Respectivamente os logos de Twitter Bootstrap e AngularJS by Google.

2- Instalando o AngularJS em seu projeto pelo Visual Studio

É muito simples instalá-lo pelo Visual Studio, com o seu projeto aberto vá no explorador de soluções e clique com o botão direito do mouse no arquivo chamado “References” e clique na opção “Manage NuGet Packages...”, como é mostrado na imagem 02 logo abaixo:

Imagem 02 Adicionando AngularJS ao projeto .

Quando o gerenciador de pacotes do NuGet abrir, no canto superior direito da tela haverá um campo de pesquisa, clique no mesmo e pesquise “AngularJS”(aguarde carregar, pois ele pode demorar alguns segundos), quando carregar os pacotes, clique na segunda opção “AngularJS” e verifique ao lado direito a versão que está, e a ultima data que foi publicada a versão, caso seja versão 1.3.14 ou superior, clique em “Install” e aguarde a instalação, como é feito na imagem 03.

Imagem 03 Instalando AngularJS.

Depois de instalar as bibliotecas do AngularJS, podemos ir até a pasta Scripts no gerenciador de soluções e veremos que haverá vários arquivos com o nome de angular e em seguida a versão, mas neste artigo, utilizaremos apenas o angular.min.js e o angular-animate.min.js, ambos são arquivos “minificados” para um melhor carregamento, neste artigo irei mostrar como adicionar o

Bootstrap e AngularJS Tela de carregamento para aplicações web

Page 6: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201506

angularJS ao seu projeto pelas nuvens, note que iremos adicionar apenas a biblioteca principal e não o pacote completo de suas bibliotecas, ou seja, caso acompanhe o tópico 3, será necessário acompanhar também o tópico 4 deste artigo para que no final sua tela de pré-carregamento funcione corretamente.

3- Continue lendo se quiser adicionar o AngularJS ao seu projeto carregando-o diretamente das nuvens...(caso não vá direto para o tópico 4)

Agora irei mostrar onde conseguiremos a biblioteca do angularJS dire-tamente das nuvens para o seu projeto, que será no site “cdnjs.com”, entre neste site e pesquise por angularJS, como mostra a imagem 04 logo abaixo:

Imagem 04 Obtendo as angularJS pelas nuvens.

logo aparecerão vários resultados, o primeiro deles é a biblioteca principal do angular, e ao passar o mouse sobre a opção é possível observar que habilitará o botão “Copy”, clique na setinha ao lado do botão copy que ele dará a opção para Copiar como Script Tag do html, observe como é feito na imagem 05:

Imagem 05 Copiando o código corretamente.

Depois de copiar desta forma basta colar na página mestre de projeto, no meu caso é a _Layout.cshtml, na parte final do código antes da tag <body>

ser fechada, observe que ela fica depois da declaração do jQuery e é nesta ordem que tem os Scripts tem que ser declarados, como é mostrado na ima-gem 06 a seguir:

Imagem 06 Adicionando a tag <script> do AngularJS corretamente.

4- Adicionando o AngularJS ao projeto para que ele carregue localmente.

O primeiro passo é entrar no arquivo BundlesConfig.cs, onde são declara-dos todos os Scripts e estilos do seu projeto a serem carregados localmente, o que já comentei em artigos anteriores sobre o bootstrap com Razor e MVC, enfim, ao abrir o arquivo de pacotes será necessário ir até o final do código e criar um novo pacote de Scripts, declarando a biblioteca principal do angular.min.js (OBS: se acompanhou o tópico 3 desconsidere adicionar a angular.min.js) e a angular-animate.min.js, ou basta copiar o código abaixo:

bundles.Add(new ScriptBundle(“~/bundles/angularjs”).Include(“~/Scripts/angular.min.js”, “~/Scripts/angular-animate.min.js”));

Depois de criar o novo pacote para o AngularJS, vá até a página mestre de projeto, caso tenha dúvidas observe como é feito na imagem 07:

Imagem 07 Declarando o pacote na página mestre.

5- Escolhendo a tela de pré-carregamento ideal para o seu projeto.

Quando finalizar a declaração do AngularJS em seu projeto, vamos es-colher qual a tela de pré-carregamento ideal a será exibida, para isso iremos utilizar um recurso gratuito chamado Spinkit, nele você escolhe uma das 8 opções disponíveis e copia o código fonte da escolhida, para fazer isso siga os passos deste tópico, para começar entre no site:

http://tobiasahlin.com/spinkit/

Para o projeto do artigo escolhi a terceira opção, depois de escolher a tela de carregamento, clique na parte superior do site onde está escrito “<> Source” como é exibido na imagem 08.

Page 7: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 07

Imagem 08 Obtendo o código fonte da tela de pré-carregamento.

Ao clicar em “<> Source” será exibido um modal com o código HTML e o CSS da tela de pré-carregamento, observe na imagem 09.

Imagem 09 Diferenciando os códigos.

6- Adicionando a tela de pré-carregamento ao projeto.

Copie todo o código HTML que fica parte superior do modal, e vá até o Visual Studio na página mestre de seu projeto e cole-o logo abaixo do inicio

da tag <body>, como é exibido na imagem 10:

Imagem 10 Adicionando o código HTML ao projeto.

Agora será necessário criar um arquivo de estilos para colocar o código CSS disponibilizado pelo site do “spinkit”, para fazê-lo basta ir até o seu explorador de soluções, localizar a pasta “Content” de seu projeto e clicar com o botão direito em cima da mesma, ir em Add depois clique em Style Sheet, da mesma forma que é mostrado na imagem 11 logo abaixo:

Imagem 12 Criando um estilo para o código fonte da tela de pré-carregamento.

Ao abrir a tela para nomear o arquivo digite “spinner” e clique em OK, depois disso arquivo será aberto imediatamente, basta apagar os códigos padrão que o Visual Studio gera, e colar o código CSS copiado do “spinkit”, salve-o e feche-o. Agora iremos declará-lo no arquivo BundlesConfig.cs, abra o mesmo, e localize o StyleBundle(pacote de estilos) com o nome de Content/css, e adicione o caminho do spinner.css, basta colocar uma vírgula na frente do ultimo e digitar o caminho entre aspas duplas, como é feito no código abaixo:

bundles.Add(new StyleBundle(“~/Content/css”).Include( “~/Content/bootstrap-theme.css”, “~/Content/site.css”, “~/Content/spinner.css”));

7- Começando a escrever a função que dará vida a tela de carregamento.

Page 8: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201508

OBS: Quando estiver lendo este artigo, provavelmente este projeto já estará disponibilizado no site do TheClub para download, recomendo que vá até o site e realize o download do arquivo, pois neste artigo não explicarei como é o funcionamento de cada uma e a lógica, o que não é o objetivo do mesmo, e para quem é novo em AngularJS recomendo que copie o procure um tutorial rápido, apenas para entender como é feita a declaração da aplicação no AngularJS, e de seus controladores, logo a compreensão manipulação dos códigos disponibilizados para download será muito mais fácil.

Para começar criaremos um arquivo JavaScript dentro da pasta Scripts do projeto, como nome de “angular-funcoes”, vá até o explorador de soluções e clique com o botão direito em cima da pasta Scripts, siga por Add depois JavaScript file, como é feito na imagem 13:

Imagem 13 Adicionando ao projeto o arquivo JavaScript para as funções do AngularJS.

Ao abrir o arquivo, copie o código abaixo contendo todas as funções:

/* Criando um módulo de aplicação para o aplicativo, observe que o nome AppTheClub é o nome que defini para o meu aplicativo.*/

var app = angular.module(“AppTheClub”, [“ngAnimate”]);

/*SIMULANDO A LATENCIA DA INTERNET E O TEMPO DE CARREGAMENTO. Note que não irei declarar o ngApp no inicio da página mestre do projeto pois iremos inciá-lo nesta função, que também da vida a nossa tela de carregamento:*/

setTimeout( function asyncBootstrap() { angular.bootstrap(document, [“AppTheClub”]);

}, (3 * 1000)//basta trocar o 3 para aumentar o //tempo que a tela de pré-carregamento //é exibida. );

/* Esta função controla a raiz da aplicação, ela apenas exibe uma mensagem no Console do navegador dizendo que o aplicativo carregou corretamente:*/

app.controller( “AppController”, function ($scope) { console.log(“Aplicativo Carregado! “, $scope); });

/* Esta classe CSS controla o efeito que anima a tela de pré-carregamento quando ela termina de carregar:*/

app.directive(

“mAppLoading”, function ($animate) { return ({ link: link, restrict: “C” });

/* Esta função vincula os eventos JavaScript ao scope.*/

function link(scope, element, attributes) { /* NOTE: Estou utilizando o .eq(1) para não estilizar o Style block.*/ $animate.leave(element.children().eq(1)).then( function cleanupAfterAnimation() { element.remove(); scope = element = attributes = null; });}});

Page 9: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 09

8- Adicionando o Script do AngularJS ao projeto pelo Bun-dlesConfig.

Agora salve e feche o arquivo, vá até o BundleConfig.cs e localize o código onde declaramos o AngularJS anteriormente e adicione o caminho do arquivo que acabamos de declarar, o angular-funcoes.js, basta colocar uma virgula e colocar o caminho entre aspas duplas como é feito no código abaixo:

bundles.Add(new ScriptBundle(“~/bundles/angularjs”) .Include(“~/Scripts/angular.min.js”, “~/Scripts/angular-animate.min.js”, “~/Scripts/angular-funcoes.js”));

9- Adicionando o código necessário a página mestre para o funcionamento da tela de pré-carregamento.

OBS: O código citado a seguir estará disponível no site do TheClub para download, mesmo com o código em mãos, siga este tópico pois estará explicando a sintaxe correta do código na página mestre.

Ao finalizar, salve as alterações e feche o arquivo, em seguida abra a página mestre do projeto, no meu caso é a _Layout.cshtml, agora ire-mos começar a trabalhar nesta tela, o primeiro passo é declarar o nosso controlador do angularJS na tag body, como mostra o código abaixo:

<body ng-controller=”AppController”>

Agora também escreveremos o código CSS (Style) que dará vida a nossa tela de carregamento, para isso teremos que criar uma nova <div> e na tag de abertura da diretiva(a div), será necessário declarar a classe que utilizamos na função angularJS que escrevemos anteriormente, e na frente a referencia do Style block do nosso container, desta forma quando o aplicativo for carregado e o container(a tela de carregamento) for removida da tela, ele automaticamente será removido da DOM, , dentro da diretiva que acabamos de criar, declare uma tag <style> e feche, copie o código a seguir para dentro da tag style:

<div class=”m-app-loading” ng-animate-children>

<style type=”text/css”> div.m-app-loading { position: fixed;

/* Utilizado para definir as propriedades do final do estado de animação do ng-leave do angularJS.*/

div.m-app-loading div.animated-container.ng-leave-active { opacity: 0; }div.m-app-loading div.messaging { color: #FFFFFF; font-family: monospace; left: 0px; position: absolute; right: 0px; text-align: center; top: 50%; margin: 0 auto; /*Esta propriedade centraliza a tela de carregamento.*/ text-align: left; }div.m-app-loading h1 { font-size: 26px; line-height: 35px; margin: 0px 0px 20px 0px; }div.m-app-loading p { font-size: 18px; line-height: 14px; margin: 0px 0px 0px 0px; } </style>

Em seguida abra uma outra tag <div>, ainda dentro da que criamos, logo abaixo do style que acabamos de escrever, colocando o código que copiamos do site spinkit (fonte da tela de carregamento) dentro dela, ou basta recortá-lo

Page 10: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201510

e colá-lo dentro da diretiva, e na tag de abertura da diretiva será necessário declarar a classe que é utilizada para dar vida a tela de pré-carregamento, observe como é feito no código:

@* Esta <div> que criamos para declarar a classe declarada no style acima. *@<div class=”animated-container”>@*Este é o inicio do código que copiei do spinkit*@ <div class=”messaging spinner” >@* É necessário adicionar a classe “messaging” antes da classe spinner*@ <div class=”rect1”></div> <div class=”rect2”></div> <div class=”rect3”></div> <div class=”rect4”></div> <div class=”rect5”></div> </div> </div>

Enfim podemos compilar o projeto e verificar o funcionamento, o resultado que obtive é exibido na imagem 14 logo abaixo:

Figura 14: Tela de pré-carregamento funcionando.

Três segundos depois a tela desaparece, exibindo assim a tela principal do projeto completamente carregada, tenha em mente que esta tela de car-regamento será exibida em todas as telas do projeto, já que a declaramos na página mestre, ou seja, todas as suas páginas descendentes herdarão a tela de pré carregamento.

10- Como alterar a cor do efeito de pré-carregamento e como

obter a cor ideal através do “colorpicker”(selecionador de cores) do Visual Studio.

Neste aposto que muitos estão se perguntando “Como faço para alterar as core da tela de pré-carregamento?”, bom é muito simples, vamos começar pelo efeito, basta acessar o arquivo spinner.css que criamos, encontrar a classe onde está declarado o style background-color, na frente dele é declarada a cor, observe que ela começa com um hash “#” e em seguida 6 carácteres, entre letras e números, caros leitores este é o formato hexadecimal, caso não seja familiarizado com o formato, basta apagar os 6 caracteres após o hash(#) e apertar Ctrl + Space que o Visual Studio abrirá o colorpicker(selecionador de cores) com algumas cores aleatórias, veja como é feito na imagem 15:

Imagem 15 Abrindo o colorpicker do Visual Studio.

Mas isso não é tudo, se a cor desejada não está entre elas, não fique chateado, basta clicar no botão ao canto direito do colorpicker exibido, e será exibida a ferramenta para selecionar a as cores uma cor.

Após habilitá-lo observe na parte de baixo, ao lado esquerdo tem a opção “Opacity”(opacidade) que altera a opacidade da cor, movendo o nível de opacidade para a esquerda você deixa a cor menos opaca, deixando-o no máximo a cor fica com a opacidade normal(sem transparência), utilizando esta opção o código de cor e alterado para o tipo “rgba” que possibilita alterar a opacidade da cor, já o hexadecimal não possibilita utilizar este recurso, veja a imagem 16 logo abaixo:

Imagem 16 Demonstrando o como utilizar os recursos do colorpicker do Visual Studio.

Agora você deve estar se perguntando “Para que serve o botão no canto in-ferior direito?”, aquele botão um recurso para selecionar a tela do seu desktop, ou seja, basta você passar o mouse em cima de alguma cor que deseja obter de seu desktop e clicar nela, para exemplificar a que obtive foi a do ícone do próprio Visual Studio(código hexadecimal #68217a).

Page 11: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 11

Assim que alterar a cor do efeito da tela de pré-carregamento, é possível mudar o plano de fundo dela também, para dar um melhor contraste no mo-mento da exibição da tela, no meu caso, inverti as cores, coloquei a cor do logo do Visual Studio como plano de fundo e deixei a do efeito como branco(código hexadecimal da cor branca é #FFF).

Para alterar a cor do plano de fundo vá até a página mestre de seu projeto, e vá até a segunda classe que declaramos e localize o style de background--color, como foi feito anteriormente, apague os dígitos depois do hash(#) e pressione Ctrl + Space, e selecione a cor desejada, para se localizar melhor observe a imagem 17:

Imagem 17 Alterando a cor do plano de fundo da tela de pré-carregamento.

O Resultado obtido é o exibido na imagem 18 logo abaixo:

[email protected]

Marlon Aparecido Branco Valentino jovem desenvolvedor front-end, com conhecimento nas lingua-

gens HTML5, CSS3, JavaScript, e nas frameworks jQuery, Bootstrap, AngularJS e suas demais bibliotecas.

Sobre o autor

Imagem 18 Resultado obtido após a alteração da cor com o colorpicker do Visual Studio.

Conclusão Neste artigo demostrei uma maneira bem fácil de se criar uma tela de

pré-carregamento para a sua aplicação em AngularJS, e também algumas dicas para conhecer este framework que vem crescendo ao longo dos últimos anos. Neste tutorial não utilizamos o “.fadeOut()” do jQuery que é o mais utilizado para este efeito, e sim o “$animate” do AngularJS, uma forma alternativa para o desenvolvedor que necessita implementar estes recursos em suas aplicações Web.

Espero que tenham gostado, até a próxima!

Page 12: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201512

Caros leitores, esta é a segunda versão do nosso aplicativo relatado na edição anterior. O que temos são inúmeras melhorias em termos de perfor-mance dentre outros quesitos interessantes no que diz respeito a manipulação dos dados, linha a linha.

Porque ler um arquivo grande?

Existem muitas situações em que precisamos ler um arquivo grande, seja binário ou texto, muito utilizado para cargas em bancos, processamentos di-versos, etc; e dessa maneira negocialmente pode ter um alto custo, de grande valia para ele; não se pode perder seus dados tampouco indisponibilizar o aplicativo com erros de falta de memória. E isso é muito fácil de acontecer, a medida em que o arquivo cresce os erros também aumentam nesse sentido – é uma proporção que acompanha e ilustra esse cenário – e então, como resolver? Qual a melhor forma de abrir arquivos grandes e mostrar eles na tela?

Venho trazer uma solução otimizada – o aplicativo FastFile agora em sua versão 2.0.

Muitas mudanças aconteceram, e o mais importante é que todo proces-samento do arquivo se fará de forma rápida e elegante – multithread – e sem mais problemas de memória.

Se parar pra pensar, constatará que as alternativas encontradas na internet são um tanto desanimadoras – experimente utilizar alternativas como “Memory Mapping Files”, por exemplo. Sua aplicação vai lançar uma exceção do tipo “OutOfMemory” e encerrar o programa. Demais alternativas como objetos do tipo TStringList ou até do tipo TMemoryStream também darão o erro seme-lhante – e te frustarão – nenhum deles vai abrir e carregar o arquivo. Poderão até tentar, mas vão parar em algum ponto e abortarão o seu procedimento/função de carregamento do arquivo.

Nosso aplicativo pode demorar até alguns segundos a mais pra responder, porém dar erros de falta de memória será muito raro. Claro que muita coisa conta; vamos aos fatos:

Razões para tornar mais lenta a leitura dos arquivos:1. Se a leitura for repetida inúmeras vezes com arquivos grandes;

FastFile 2.0 – Aplicativo Leitor para Arquivos Grandes

2. Muitas janelas abertas simultaneamente com cada uma represen-tando aplicativos consumindo muita memória ao mesmo tempo;

3. Abrir mais de um FastFile ao mesmo tempo e executando os itens acima;

4. Como dito anteriormente, requisitos de hardware/software infe-riores ao recomendável (memória inferior a 3 GB/RAM, por exemplo);

5. Pouco espaço em disco;6. Antivírus que interfira no processo.

Nesta revisão do programa, em sua versão 2.0, muitas coisas foram revisadas e quase que 100% reescrito – o resultado impressiona. Além de ler e carregar o arquivo inteiro de mais de um 1GB em 20 segundos (em média) – serão mostradas duas alternativas de que “existe luz no fim do túnel” – e esperançosamente com a própria VCL – sem nenhum componente adicional ao nosso aplicativo. A novidade é explorar recur-sos de extração de partes via TMemoryStream e exibi-los inteiramente em um TListView virtual e também através de um TClientDataSet aces-sado via multithread, salvando em um campo do tipo ftBlob e indexado – assim o arquivo pesado será aberto, lido e carregado sem nenhum problema! A primeira alternativa (TListView) é a mais recomendável por ser mais veloz e menos propensa a erros do que a segunda. O programa vai carregar todo o conteúdo de arquivos “gigantes” (testado com até 1.2 GB de tamanho) – mas poderá ser avaliado com arquivos maiores ainda do que este – depende muito da memória do computador em questão bem como a velocidade do processador, e não por último a capacidade do HD disponível.

Recomendações Iniciais

Este aplicativo requer algumas configurações básicas para melhor per-formance. São estes fatores em que foram testadas – e é principalmente esta configuração de hardware que deve ser levado em conta.

1. Memória Mínima 3GB RAM (testada e recomendada: 4GB RAM);2. Espaço HD – mínimo 15 GB;3. Velocidade Processador 2.50 GHz4. Permissão de leitura e gravação do diretório onde o arquivo se

encontra.

Page 13: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 13

Criação do Cenário – Primeira Alternativa

Agora vamos explicar como vai ser o nosso ambiente. E é como será lido o arquivo. Ele será lido parte por parte – teremos um objeto chamado StrmInput (TFileStream) que apenas criará o arquivo no nosso programa – e assim será lido parte por parte sequencialmente, através de um valor que define auto-maticamente o tamanho de cada parte (implementadas em um algoritmo próprio – nossa função NumberOfPartsToDivide) onde por sua vez representa o total de partes a serem lidas, relação “tamanho original do arquivo/tamanho padrão de cada parte = número de partes a serem lidas”.

Por exemplo, um arquivo contendo 455872375 bytes será gerado o ta-manho de cada parte de 455900 bytes, onde a quantidade de partes é 1000 (455872375/455900 = 999,9394055713972 => arredondamento de 1000). No nosso caso o arquivo se chama “loadfile03.txt” e apresenta o tamanho (de acordo com o MsExplorer) de 445.188 KB (em bytes – 455872375).

Cálculo:

Observação: Leia-se comprimento e tamanho – termos idênticos para a exemplificação

do processo.

Descrição:Em fração, o denominador corresponderá a quantidade de partes exatas

em que será dividido o arquivo, enquanto que o numerador será o tamanho do arquivo.

Variáveis envolvidas: Numerador e Denominador.

Fórmula Intermediária: Numerador:Corresponde ao tamanho original do arquivo, em bytes.

Denominador:Base 10 elevada ao expoente (comprimento do arquivo original – compri-

mento arredondado do arquivo original dividido por 2) – onde se o compri-mento do arquivo for de 1 e 2 será auto-definido por 4 e 8, respectivamente. Portanto, denominador será 10tamanho arquivo original – tamanho div/2.

Fórmula Final: Arredondamento (Numerador/Denominador) * 100.

Com isso, será retornado o valor padrão do tamanho de cada parte a ser dividida. Quanto maior o arquivo, maior o tamanho de cada parte a ser dividida (proporcionalmente à fórmula gerada).

Segue abaixo trecho do código-fonte da implementação da função Num-berOfPartsToDivide:

function TfrmMain.NumberOfPartsToDivide(const filesize: integer): integer;var

denominator: integer; { In fraction, the denominator will match the amount of exact parts where the file will be divided, while the numerator is the file size. Em fração, o denominador corresponderá a quantidade de partes exatas em que será dividido o arquivo, enquanto que o numerador será o tamanho do arquivo. }begin case length(IntToStr(Round(filesize))) of //convert to bytes 1: denominator := 4; 2: denominator := 8; else denominator := Round(Math.Power(10, length(IntToStr(filesize)) - Round(length(IntToStr(filesize)) / 2))); end;

Result := Round(filesize/denominator) * 100;end;

A parte gerada de um arquivo (chamada PartFileSize) será sempre a diferença entre o tamanho total do memoryStream utilizado (size) menos a posição atual (position) – sempre verificado antes se o tamanho total menos a posição atual é menor que esta parte gerada, como podemos ver no trecho seguinte abaixo:

StrmInput := TFileStream.Create(StrFilename,fmOpenRead or fmShareDenyNone);try{…}while (StrmInput.Position < StrmInput.Size) and (Tag = 0) do begin StrmOutput := TMemoryStream.Create; try if StrmInput.Size - StrmInput.Position < PartFileSize then PartFileSize := StrmInput.Size - StrmInput.Position;

Page 14: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201514

StrmOutput.CopyFrom(StrmInput,PartFileSize); finally FreeAndNil(StrmOutput); End; { …} Finally FreeAndNil(StrmInput);end;

Figura 01 – Diretório dos arquivos texto utilizados no FastFile.

Processamento do Arquivo – Primeira Alternativa

Esta primeira alternativa na minha opinião é a melhor de ambas – utiliza recursos da classe TThreadList , que é uma lista de Threads, chamando nossa implementação particular de TList – FLineReaderList – inserindo nela as linhas (número e conteúdo de cada uma) e também para incrementar uma variável contadora chamada Counter (definida em TMyObject) .

A estrutura de leitura linha a linha: TLineReader

A classe TLineReader representa nossa excelência de solução de leitura de cada linha do arquivo desejado. Essa leitura será feita extremamente rápida, por ser implementada em uma classe TLineReaderList (TList) – onde cada item desta classe referenciará internamente os objetos de TLineReader.

Funciona assim:

1. TMyObject é a classe que implementa um contador global;2. TLineReader implementa leitura por linha (que vai ler parte por

parte do arquivo);3. TLineReaderList implementa um conjunto de TLineReader, herdando

do tipo TList;4. TThreadList é a lista de threads que chamará TMyObject, obterá

o contador atual, e incluirá na nossa lista TLineReaderList as referências de TLineReader nela;

5. O contador Counter de TMyObject é incrementado juntamente com a nossa variável global lineCounter;

6. É feito o sincronismo com a VCL através de um objeto progressbar (TProgressBar) para reportar à tela o andamento da execução desta operação;

7. Após essa etapa todos os dados da estrutura TLineReaderList estarão disponíveis para o nosso TListView, apresentando rapidamente sob demanda todas as que forem requisitadas por ele dinamicamente. E não haverá problema de memória para esta operação.

A classe TLineReaderList é importante para o nosso processamento do arquivo; como ela herda de TList (que é uma lista de ponteiros) – ela lerá todo o conteúdo do arquivo desejado – linha a linha, armazenando o id da linha e o conteúdo desta id – cada id representará uma linha em si – implementamos a função GetItem utilizada para a propriedade da coleção Items em

property Items[Index: Integer]: TLineReader read GetItem; default; por-tanto segue o código-fonte abaixo que declara nossas estruturas de leitura de linhas de arquivo:

//class to implement a “global counter” used for its connected threadstype TMyObject = class private Counter: integer; public constructor Create(const iCounter: integer); end;

var ThreadList: TThreadList;

// The line class definitiontype TLineReader = class private FContents: string; FLine: Integer; public // Properties to read these data values property Contents: string read FContents write FContents; property Line: Integer read FLine write FLine; // Constructor constructor Create(const AContents: string; const ALine: Integer); end;

// The typed list of TLineReader objects TLineReaderList = class(TList) private function GetItem(Index: Integer): TLineReader;

Page 15: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 15

public property Items[Index: Integer]: TLineReader read GetItem; default; end;

Descrição do Processo de Leitura – Passo a Passo

Assim sendo, cada parte dividida pelo programa será lido linha a linha por esta estrutura.

1. O programa carregará o arquivo;2. O programa dividirá o arquivo em várias partes pré-definidas por

ele mesmo;3. Para cada parte dividida será disparada uma thread para ela, que

por sua vez terá o objetivo de ler cada linha destas partes divididas;4. Apenas uma thread por vez vai gravar na estrutura de lista TLineRe-

aderList o id e o conteúdo das linhas, para que não ocorra acesso simultâneo entre elas e consequentemente violação de acesso;

5. Após o processamento da leitura de todas as partes, constituídas por todas as suas threads (cada parte tem a sua thread) a nossa função de processamento chamará um objeto da classe TListView em modo virtual – e é aqui onde a brincadeira começa.

O objeto de TListView imprimirá os dados das leituras, linha a linha, na tela do aplicativo, sendo renderizado dinamicamente por um objeto do tipo TScroll-Bar. E a velocidade é extremamente rápida – por ser virtual o nosso TListView não armazena os dados em si, ela depende de uma estrutura auxiliar que os armazene – e é aqui onde entra nossa estrutura TLineReaderList, que como já foi dito, é baseada em TList, portanto é baseada em lista de ponteiros – o que temos aqui é armazenamento de milhões de linhas em poucos segundos – uma média de 20 segundos para leitura integral de um arquivo de 1,2 GB. E sem “travar” a tela, lançar exceções de memória insuficiente ou coisa assim. Há a certeza de que o caminho feliz do fluxo chegará com sucesso e podemos repetir a operação quantas vezes forem necessárias – todos os objetos da lista serão removidos e destruídos (com a memória desalocada) como em:

“for i := 0 to FLineReaderList.Count - 1 do TObject(FLineReaderList[I]).Free;”“FreeAndNil(FLineReaderList);”

ListView Virtual

Um objeto de TListView é um objeto extremamente útil. Pode se comportar de varias formas, isto é, tem vários tipos de visualização, formatação, etc. A lista de arquivos do MsWindowsExplorer é um objeto de TListView.

O componente TListView é um encapsulamento do componente ListView do Windows. Ele é muito interessante no que diz respeito a sua flexibilidade de customização, podendo por exemplo utilizar o estilo de visualização “ViewS-tyle” como “vsList”,“vsReport”, etc; dentre outras inúmeras possibilidades. É

um componente que pode ser utilizado como um contêiner para o recordset de uma consulta de um banco de dados, respostas de uma procura de itens de arquivos resultantes de TSearchRec, dentre outras mil opções disponíveis.

Por isso, sua utilização é muito satisfatória, podendo substituir componen-tes como TDBGrid e TStringGrid sempre que possível; bastando implementar eventos necessários para o CRUD (Create/Read/Update/Delete) do dataset desejado, mas também é tranquila sua adaptação.

O problema é a quantidade de registros que deseja mostrar nele. Só isso. Se desejamos mostrar um milhão de registros, por exemplo, vai travar! Será um problema e sua aplicação ficará com a tela “congelada” podendo dar também erros de falta de memória, memória insuficiente, etc; o que fazer nesse caso? Como resolver se os dados são muito volumosos?

A resposta é a seguinte: Use um TListView virtual.

Aí nesse caso tudo vai melhorar, pois nosso objeto de TListView apenas vai solicitar os itens que deseja mostrar, aumentando muito a velocidade de apre-sentação. Isso acontece porque o objeto de TListView virtual não é proprietária de seus itens. Ela não sabe o que ela guarda dentro de si mesma. E na verdade ela não guarda mesmo, quem vai guardar vai ser uma estrutura auxiliar dentro dela que dará esse suporte. Essa estrutura é o programador quem vai decidir o que vai escolher, pois existem milhares de opções. Ele vai sobreescrever o evento OnData dela, que é o evento utilizado para renderizar linha a linha deste TListView apresentado. Então, todos os dados vão ser carregados por esta estrutura e exibido em tempo de execução “sob demanda” – ou seja – sempre que o usuário solicitar, linha a linha, estes dados são desenhados no momento em que são visualizados – e não todos de uma só vez – como seria se fosse não-virtual (o modo tradicional). A vantagem é a velocidade admirável de renderização – e não custa memória, pois no nosso caso empregaremos uma estrutura baseada em TList – que quer dizer, uma lista baseada em ponteiros. TList é uma lista (coleção) de objetos, acessível por um índice, onde este índice retorna demais atributos deste objeto relacionado dentro dela, podendo criar novos objetos, alterar, remover, etc; pode-se limpar a lista inteira e até inserir objetos nulos (nil) dentro dela. Pode-se também definir e recuperar valores (set/get, respectivamente) utilizando a indexação do array Items dela. Ou seja, é muito importante sua utilização, porque como é referenciada diretamente na memória, ela é muito rápida.

Figura 02 – Template de um exemplo de TListView virtual

Segue abaixo um exemplo de fonte de como gerar alguns registros dina-micamente, para dentro de nossa estrutura auxiliar (TLineReaderList) que fará o papel de “suporte de armazenamento auxiliar” para a renderização virtual de nosso objeto de TListView:

Page 16: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201516

procedure TForm1.Button1Click(Sender: TObject);var i: integer; totalItens: integer;begin// MyList := TList.Create; counter := 0; FLineReaderList := TLineReaderList.Create;

totalItens := 5000; ProgressBar.Max := totalItens; ProgressBar.Position := 0;

for i := 0 to totalItens do begin // MyList.Add(pinteger(i));

FLineReaderList.Add(TLineReader.Create(‘Added new item’, i)); ProgressBar.Position := ProgressBar.Position + 1; Application.ProcessMessages; end;

ListView1.OnData := ListView1_Data; ListView1.Refresh; ShowMessage(‘pronto’);end;

De acordo com o código acima, a renderização será feita automaticamente porque o objeto de TListView saberá o que buscar na hora de exibir os dados – nem tudo é mostrado ao mesmo tempo, mas “sob demanda”, ou seja, a medida em que as linhas são exibidas para o usuário o componente se encarrega de chamar nossa estrutura auxiliar de apoio para mostrar os dados em seu lugar – e dessa forma os dados são apresentados de forma dinâmica – e o que isso significa? Mais rapidez de exibição dos dados. Lembre-se sempre de utilizar o evento OnData dele, pois é lá que nossa estrutura auxiliar TLineReaderList será chamada linha a linha, conforme código abaixo:

procedure TfrmMain.ListView1_Data(Sender: TObject; Item: TListItem);function getLineContentsFromLineIndex(const iLine: integer): string;begin Result := ‘-’;

if (iLine >= 0) and (iLine <

FLineReaderList.Count) then Result := (FLineReaderList.Items[iLine].Contents);end;var Index: Int64;begin // Item.Index now represents an offset from an offset, adding them together // gives the true index Index := Offset + Item.Index; Item.Caption := ‘Line: ‘ + IntToStr(Index) + ‘ ‘ + getLineContentsFromLineIndex(Index);end;

Assim sendo, a função getLineContentsFromLineIndex retorna sempre o conteúdo atual de TLineReaderList (FLineReaderList.Items[iLine].Contents) – chamado linha a linha pelo TListView virtual. Repare nos parâmetros do evento OnData (Sender: TObject; Item: TListItem) – o segundo parâmetro é o índice da linha! E ele fará referência à nossa função – chamando linha por linha – mas nossa estrutura é baseada em TList – então não haverá problema – é memória pura, rapidez garantida na resposta. Fazendo um teste de performance, se inicializássemos nosso objeto de TListView como ItemCount := High(Int64) teríamos em menos de um segundo a compilação apresentando a renderização dinâmica de todas as linhas criadas de 0 até 9223372036854775807 linhas!

Figura 03 – Teste de apresentação da renderização das linhas em modo virtual, intervalo de 0 a 9223372036854775807 linhas (High(Int64)).

Figura 04 – Teste de apresentação da renderização das linhas em modo virtual,

Page 17: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 17

intervalo de 0 a 9223372036854775807 linhas (High(Int64)).

Apresentação dos dados - ListView Virtual no FastFile

O nosso objeto de TListView vai exibir os dados no final, quando o objeto de TProgressBar finalizar a contagem das partes lidas do arquivo. Para cada parte será chamada uma thread para lê-la, conforme já dito anteriormente:

1. Parte do arquivo gerada;2. TFileSaveThread criada para ler a parte;3. Objeto de TStringList para ler o conteúdo total da parte;4. Loop no objeto de TStringList para acrescentar cada item dele

na estrutura FLineReaderList (frmMain.FLineReaderList.Add(TLineReader.Create(strList.Strings[i], obj.Counter));

5. Definir a quantidade de linhas no TListView conforme nosso con-tador global atualizado entre as threads (sincronismo) – como em ListView1.Items.Count := Min(ItemCount, lineCounter);

6. Exibir o objeto de TListView virtual na aplicação.

Figuras 05 e 06 – Exibição do FastFile com o arquivo carregado – no teste um arquivo texto de carga chamado “LoadFile05.txt” com o tamanho de 1.284.808 KB, carregado em 24 segundos, com o objeto de TListView em modo virtual renderizando um total de 11064232 linhas.

Associação com objeto TScrollbar

O nosso objeto de TListView não vai exibir tudo ao mesmo tempo, como já sabemos. O que muda aqui é como o sincronismo entre os dados e sua exi-bição é controlado – não há o suporte direto de barras de rolagem – estamos no modo virtual - quem vai fazer esse papel é um objeto da classe TScrollbar.

Para que isso realmente tenha eficiência, precisamos realizar a troca de informações entre as linhas do TListView com o evento OnScroll do TScrollbar. Segue código-fonte abaixo de como isso será feito.

procedure TfrmMain.ScrollBar1Scroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);var MaxOffset: Int64;begin // Int64 support for scrollbar, etc MaxOffset := ItemCount - VisibleItems + 1; case ScrollCode of scLineUp: begin if Offset > 0 then Offset := Offset - 1; end; scLineDown: begin if Offset < MaxOffset then Offset := Offset + 1; end; scPageUp: begin if Offset > VisibleItems then Offset := Offset - VisibleItems else Offset := 0; end; scPageDown: begin if (MaxOffset - Offset) > VisibleItems then Offset := Offset + VisibleItems else Offset := MaxOffset; end; scPosition, scTrack: begin Offset := Trunc((ScrollPos / Scrollbar1.Max) * MaxOffset); Exit; end; scTop: begin Offset := 0; Exit; end; scBottom: begin Offset := MaxOffset; Exit; end; scEndScroll: begin

Page 18: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201518

end; end; ScrollPos := Trunc((Offset / ItemCount) * ScrollBar1.Max); ListView1.Refresh;end;

procedure TfrmMain.ScrollBar1Change(Sender: TObject);begin ListView1.Refresh;end;

TFileSaveThread – Nossa thread de leitura

Nosso ambiente multithread é o que fará diferença neste processo de leitura, somando ao fato do objeto de TListView estar em modo virtual. São estas duas características que “aceleram” esta funcionalidade.

Nossa thread chamará o método FileReadMemory, que fará a realização de leitura das linhas internamente para a nossa declarada estrutura TLine-ReaderList. Segue o fonte abaixo de sua implementação, e onde está sendo empregada:

TFileSaveThread = class(TThread) protected procedure Execute; override; public Id: integer; strSplittedText: string; constructor Create(CreateSuspended: Boolean; const myID: integer; const mySplittedText: string); procedure FileReadMemory; end;

constructor TFileSaveThread.Create(CreateSuspended: Boolean; const myID: integer; const mySplittedText: string);begin inherited Create(CreateSuspended);

Self.Id := myID; Self.strSplittedText := mySplittedText;

Priority := tpNormal;end;

procedure TFileSaveThread.Execute;begin FreeOnTerminate := True;

Synchronize(FileReadMemory);end;

procedure TFileSaveThread.FileReadMemory;var strList: TStringList; i: integer; list: TList; obj: TMyObject;begin strList := TStringList.Create; list := ThreadList.LockList;

try strList.Text := (Self.strSplittedText); obj := TMyObject(list[0]);

for i := 0 to strList.Count - 1 do begin frmMain.FLineReaderList.Add(TLineReader.Create(strList.Strings[i], obj.Counter)); inc(obj.Counter); Inc(frmMain.lineCounter); end;

frmMain.RefreshProgressBar; finally FreeAndNil(strList); ThreadList.UnlockList; end;

end;

StrmInput := TFileStream.Create(StrFilename,fmOpenRead or fmShareDenyNone); try Self.Disable; try while (StrmInput.Position < StrmInput.Size) and (Tag = 0) do begin SequentialFile := ChangeFileExt((ExtractFilePath(StrFilename) +

Page 19: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 19

IncludeTrailingPathDelimiter(tempFolder) + ExtractFileName(StrFilename)),’.’+Format(‘%.03d’,[FileNumber]));

SequentialId := StrToIntDef(Self.ExtractFileExtAfterDot(SequentialFile), 0); //StrmOutput := TFileStream.Create(SequentialFile ,fmCreate); ==> Don´t use: it´s very slow !! StrmOutput := TMemoryStream.Create; try if StrmInput.Size - StrmInput.Position < PartFileSize then PartFileSize := StrmInput.Size - StrmInput.Position;

StrmOutput.CopyFrom(StrmInput,PartFileSize); case fSelectedType of StPartRead: TFileReadThread.Create(False, SequentialFile, SequentialId, {PartFileSize,} Biblioteca.MemoryStreamToString(StrmOutput)); StMerge: TFileSaveThread.Create(False, SequentialId, Biblioteca.MemoryStreamToString(StrmOutput)); end;

Application.ProcessMessages; finally FreeAndNil(StrmOutput); end; Inc(FileNumber); end; finally FreeAndNil(StrmInput); end;

Segunda parte de leitura de arquivos – o ClientDataSet de apoio

Nesta segunda parte, haverá uma alteração em como será realizada a leitura de arquivos. As partes divididas deste arquivo serão gravadas direta-mente em um objeto de TClientDataSet, ao invés de ser gravada naquela nossa estrutura de apoio TLineReaderList.

Pessoalmente, prefiro a primeira opção, a que foi explicada até agora. O TListView se comporta mais eficiente e “seguro” na renderização das linhas de texto do que um objeto de TClientDataSet realizaria. Muitos testes e esforços para unir do “útil ao agradável” fazendo um merge de tudo para um TClien-tDataSet falharam e me frustraram – não é tão eficiente quanto a primeira alternativa – o TListView vence em disparada. Então pra que abordar ele agora? Mais para uma questão didática – de como o processo pode ser salvo parte a parte em um fluxo alternativo, onde clicando na parte desejada todo o conte-údo da mesma é impresso na tela para o usuário. Em vez de ir renderizando as linhas por meio de um objeto TScrollBox todo o conteúdo já é disponível em um objeto TMemo – não é a mesma coisa. Mas funciona, desde que com bom-senso (não foi testado à exaustão) e sinceramente, algumas vezes a me-mória reclama enviando exceções ao compilador de insuficiência de memória.

O leitor vai preferir a primeira opção, por raramente apresentará erros de falta de memória.

Com o TListview, mesmo com estas razões citadas acima a aplicação ainda funciona, possivelmente um pouco mais lento – alguns segundos a mais – mas travar já será algo mais difícil de acontecer. O mesmo já não será possível dizer com a segunda alternativa – o TClientDataSet – chamar ele a cada thread não foi um resultado tão satisfatório – a promessa de ler todas as partes de um arquivo grande em questão pode falhar. Assim, o mais seguro é a primeira alternativa.

Figuras 07/08/09 – Exibição do FastFile com a segunda opção escolhida – com o

objeto TClientDataSet em ação.

Page 20: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201520

Figuras 10/11 – Exibição do FastFile com a segunda opção escolhida – com o objeto TClientDataSet em ação – carregando o nosso arquivo texto de carga – o “loadfile05.txt” com 1.2 GB de tamanho.

Comparação final: TListView x TClientDataSet

Fator TListView TClientDataSetAgilidade Sim Sim

Carregamento do arquivo Sim Sim, mas pode falhar

Leitura das partes do arquivo Sim Sim, mas pode falhar

Re-leitura Sim Sim, mas pode falhar

Eficiência Sim Sim/Não

Confiabilidade Sim Sim/Não

Acesso direto às partes Não Sim

Editar manualmente as partes Não Sim

Leitura Virtual para Agilidade Sim Não

Portanto, melhor opção eleita: TListView! É o componente que lerá todos os dados velozmente e quantas vezes forem necessárias, sem correr o risco de perder os dados da leitura no meio do caminho. Lembrando que o compo-nente deve estar em modo virtual, com a propriedade OwnerData como True.

Conclusão

Vimos duas alternativas interessantes para a leitura de arquivos grandes. O propósito do aplicativo desenvolvido especialmente para esta edição (Fas-tFile) é na verdade um mero leitor de arquivos, com sua ideia de dividi-lo em partes e ler cada uma delas, pois quebrando o arquivo em partes e lendo é mais fácil e mais rápido do que ler ele todo de uma vez, sem falar que lendo todo ele de uma vez não vai funcionar se o arquivo é muito grande. Vai dar erros de falta de memória, memória insuficiente, etc; e a leitura não vai ser feita. Daí esta minha implementação que felizmente resolve para este tipo de questão. Esperar alguns segundos para ler arquivos de mais de um 1 GB não é um trabalho árduo de paciência pra ninguém – um objeto de progresso (TProgressBar) notificará o andamento da rotina passo a passo para certificar ao usuário que o FastFile está trabalhando, com as threads de leitura em segundo plano, para carregar o arquivo e disponibilizar ele nos objetos instanciados (classe TListView/TClientDataSet) e assim poder lê-lo integralmente e sem problema algum.

O aplicativo lerá linha a linha dos arquivos (opção 1) – mas ele não processa elas – poderia ser implementado um evento de resposta a isso – recomendá-vel para parametrizações com um banco de dados, por exemplo – algo como “OnProcessLine(const iLine: index; const strFrase: string)”. O que discutimos aqui é o mais complexo – é o processamento da leitura em si, linha a linha – e não o que fazer com elas, além de exibi-las! Pois o fator tamanho é crucial para o desempenho e a eficiência do nosso processo de leitura. Sem uma alternativa viável como implementamos, não seria possível tradicionalmente realizar esse processamento dispendioso de memória pelos métodos padrões. Daí nossa construção do FastFile.

Portanto, conforme eu já disse ele é um mero leitor de arquivos, porque o leitor não vai esperar outras funcionalidades contidas no FastFile – claro que muitas coisas poderiam ser acrescentadas, mas isso já assunto para outros artigos. Sugestões são sempre bem-vindas, o programa é freeware, portanto sinta-se a vontade, boa diversão com os fontes inclusos, apenas uma citação de copyright ao meu nome e tudo está resolvido. Bons estudos e até a próxima!

[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 21: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 21

Neste mês abordarei um assunto presente em todos os sistemas, o uso de autenticação de usuários, ou seja, criarei uma tela de login para quem está desenvolvendo para a plataforma Android. Com os recursos do Android em sua versão 4.4 poderemos implementar técnicas muito legais para esta tarefa. No primeiro momento será criada uma classe contendo dados do usuário, como por exemplo: “Usuário” e “Senha”. A Tela de Login será herdada de uma “Activity” e o lay-out será desenhado a partir de um arquivo “.xml”, ou seja, não teremos nada de diferente.

Criando o Exemplo

O primeiro passo seria criar o projeto, para quem não sabe clique em “File/New/Android Application Project” definindo um Nome para a aplicação, projeto e o pacote. No meu caso foi definido como:

Application Name: LoginProject Name: LoginPackage Name: com.example.login

Recomendo também fazer o uso do SDK 4.4 - API 19, o Android 4.4 KitKat. Ver Imagem 01.

Figura 01: Criando uma aplicação Android.

Android – Criando uma Tela de Login

Os próximos passos deveremos seguir as configurações padrões de projeto. (Não detalharei esta etapa pois temos inúmeros artigos em nossa revista sobre este assunto). Com o projeto criado podemos notar a presença de uma Activity chamada “MainActivity.java” e de um arquivo de lay-out “activity_main.xml”, ambos serão aproveitados para chamar a nossa tela de Login mais adiante. Partiremos então para a criação da classe “Login”.

Classe “Login.java”

Clique com o botão direito sobre o diretório “src/com.example.login” e escolha o item “New/Class”. Esta classe irá conter os atributos “Usuario” e “Senha” com os respectivos “Gets” e “Sets” e o método “ValidarUsuario()”. Teremos como referência o uso de duas constantes do tipo texto, sendo USU-ARIO e SENHA. Farei o uso das mesmas para fins didáticos, mas ressalto que poderíamos receber estes dados de outra origem, como por exemplo de um banco de dados. Ver Listagem 01.

package com.example.login;

public class Login { private static final String USUARIO = “THECLUB”; private static final String SENHA = “123456”;

Teremos as duas constantes do tipo texto contendo valores padrões.

private String Usuario; private String Senha; public String getUsuario() { return Usuario;

Page 22: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201522

}

public void setUsuario(String usuario) { Usuario = usuario; }

public String getSenha() { return Senha; }

public void setSenha(String senha) { Senha = senha; }

Teremos também os atributos “Usuário” e “Senha” devidamente encap-sulados.

public Login() { }

No método construtor não faremos nada de diferente.

public boolean ValidarUsuario() { if (Usuario.equals(“”)) { return false; } else if (Senha.equals(“”)) { return false; } else if (!Usuario.equals(USUARIO) || !Senha.equals(SENHA)) { return false; } else { return true; } }

No método “ValidarUsuario()” não teremos nenhum parâmetro de en-trada e sim um de saída. Retornaremos um valor booleano realizando um encadeamento de “ifs” testando se o atributo Usuário ou Senha estão vazios e se os mesmos correspondem aos valores definidos nas constantes. Através do resultado deste método validamos os dados digitados.

}Listagem 01: Classe Login.

O nosso projeto de exemplo possuirá as seguintes atividades com seus respectivos arquivos “XML”, podemos conferir detalhadamente abaixo:

1) MainActivity.java/activity_main.xml (Tela que conterá a chamada para a tela de Login)

2) LoginAtividade.java/login.xml (Tela para efetuar o Login)3) CadastroAtividade.java/cadastro.xml (Tela que se abrirá após a auten-

ticação do usuário)

Respeitando a estrutura descrita acima, deveremos criar todos os arquivos responsáveis pelo funcionamento do projeto, ver Figura 02.

Figura 02: Estrutura do projeto.

Page 23: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 23

Listagem 2

1) Main_activity.xml

Nesta tela teremos apenas um botão responsável por chamar a tela de login. Através dele disparamos o método “OnActivityResult” que será discutido logo em seguida. Ver Figura 03.

Figura 03: Tela para chamar o Login.

O XML correspondente, Ver Listagem 02.

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android” xmlns:tools=”http://schemas.android.com/tools” android:layout_width=”match_parent” android:layout_height=”match_parent” android:paddingBottom=”@dimen/activity_vertical_margin” android:paddingLeft=”@dimen/activity_horizontal_margin” android:paddingRight=”@dimen/activity_horizontal_

margin” android:paddingTop=”@dimen/activity_vertical_margin” tools:context=”.MainActivity” > <Button android:id=”@+id/btnLogin” android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:layout_centerHorizontal=”true” android:onClick=”Login” android:text=”Efetuar Login” /></RelativeLayout>

Codificando a Atividade “main_activity.java”

Nesta atividade teremos que nos focar no método “Login” e no “OnActi-vityResult”, sendo respectivamente para invocar a tela de login e para tratar o retorno do mesmo.

Conferir Listagem 03.

package com.example.login;

import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.view.Menu;import android.view.View;

Importaremos algumas bibliotecas essenciais.

public class MainActivity extends Activity {

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

Page 24: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201524

Listagem 5

setContentView(R.layout.activity_main); }Método que será disparado na criação do lay-out. public void Login(View view) {Intent login = new Intent(MainActivity.this, LoginAtividade.class); startActivityForResult(login, 1); }

Método que fará a chamada da Atividade “LoginAtividade”. Trataremos o retorno da mesma através da função “StartActivityForResult”.

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == Activity.RESULT_OK && requestCode == 1) {startActivity(new Intent(MainActivity.this, CadastroAtividade.class)); } }

Já no método sobrescrito “OnActivityResult” comparamos o atributo “resultCode” para nos certificarmos que o usuário clicou no botão “OK” e o “requestCode” para o valor 1, indicando que a autenticação foi realizada com sucesso.

}Listagem 03.

2) login.xml

Deveremos inserir dois TextViews, dois Editexts e um Button, com as informações referentes ao usuário. Ver Imagem 04.

Figura 04: Tela de Login.

O XML correspondente, conferir Listagem 05.

<?xml version=”1.0” encoding=”utf-8”?> <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android” android:layout_width=”fill_parent” android:layout_height=”fill_parent” android:orientation=”vertical” android:padding=”5dp” > <TextView android:id=”@+id/txtLogin” android:layout_width=”match_parent” android:layout_height=”wrap_content” android:text=”Usuário” android:textAppearance=”?android:attr/textAppearanceMedium” /> <EditText

Page 25: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 25

android:id=”@+id/edtUsuario” android:layout_width=”match_parent” android:layout_height=”wrap_content” android:ems=”10” > </EditText> <TextView android:id=”@+id/txtSenha” android:layout_width=”match_parent” android:layout_height=”wrap_content” android:text=”Senha” android:textAppearance=”?android:attr/textAppearanceMedium” /> <EditText android:id=”@+id/edtSenha” android:layout_width=”match_parent” android:layout_height = “wrap_content” android:ems=”10” android:inputType=”textPassword” /> <Button android:id=”@+id/btnEntrar” android:layout_width=”match_parent” android:layout_height=”wrap_content” android:onClick=”Login” android:text=”Entrar” /> </LinearLayout>

Codificando a Atividade “LoginAtividade.java”

Já na “LoginAtividade” iremos alimentar a classe “Login” criada anterior-mente com os dados necessários. Ver Listagem 06.

package com.example.login;

import android.app.Activity;import android.app.AlertDialog;import android.os.Bundle;import android.view.View;import android.widget.EditText;

Faremos o uso de algumas bibliotecas.

public class LoginAtividade extends Activity { private EditText edtUsuario; private EditText edtSenha;

Deveremos declarar duas variáveis privadas, ambas para inicializar os “EditTexts”.

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); InicializaObjetos(); } public void InicializaObjetos() {edtUsuario = (EditText) findViewById(R.id.edtUsuario); edtSenha = (EditText) findViewById(R.id.edtSenha); }

O método “InicializaObjetos” irá realizar a referência dos objetos com as variáveis criadas acima. Este método sempre será disparado no evento “OnCreate”.

private void MensagemInformativa(String mensagen) { new AlertDialog.Builder(this) .setTitle(“The Club”) .setMessage(mensagen) .setPositiveButton(“OK”, null) .setCancelable(false) .show(); }

Page 26: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201526

Listagem 7

O método “MensagemInformativa” recebe como parâmetro uma variável do tipo texto que nos dará uma mensagem informativa ao usuário de acordo com a ocasião. Ele faz o uso da classe “AlertDialog” com alguns atributos como por exemplo: “setTitle” (Inserir título na caixa de diálogo), “SetMessage” (Mensagem disparada), “setPositiveButton” (Botão Ok) e “set Cancelable” (in-dicando que não possui o botão cancelar) e o método “show” (para carregá-lo).

public void Login(View v) { Login classe_login = new Login();classe_login.setUsuario(edtUsuario.getText().toString()); classe_login.setSenha(edtSenha.getText().toString()); if (classe_login.ValidarUsuario() == false) {MensagemInformativa(“Dados Incorretos, Favor preenchê-los corretamente!”); } else { setResult(Activity.RESULT_OK); finish(); } }

O método “Login” recebe como parâmetro a própria View, sendo disparado no evento “OnClick” do Botão. Deveremos instanciar a classe “Login” setando o usuário e a senha logo em seguida. Faremos um “If” com base no método “classe_login.ValidarUsuario()” comparando se o retorno é verdadeiro ou falso. Caso o retorno for “falso” disparamos uma mensagem para o usuário, caso contrário liberaremos o acesso com o auxílio do método “setResult” e o “finish()” para fechar a nossa Atividade.

}Listagem 06.

3-) cadastro.xml

Esta tela seria apenas para informar ao usuário que o acesso foi liberado. Fiquem a vontade para utilizar o que desejar. Ver Imagem 05.

Figura 05: Tela informativa de acesso liberado.

O código XML na Listagem 07.

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android” xmlns:tools=”http://schemas.android.com/tools” android:layout_width=”match_parent” android:layout_height=”match_parent” android:paddingBottom=”@dimen/activity_vertical_margin” android:paddingLeft=”@dimen/activity_horizontal_margin” android:paddingRight=”@dimen/activity_horizontal_margin” android:paddingTop=”@dimen/activity_vertical_margin”>

Page 27: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 27

Listagem 8

<TextView android:id=”@+id/txtMensagem” android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:layout_alignParentTop=”true” android:layout_centerHorizontal=”true” android:layout_marginTop=”64dp” android:text=”Acesso Liberado!!!” android:textSize=”30dp” android:textAppearance=”?android:attr/textAppearanceLarge” />

</RelativeLayout>

Configurações no “AndroidManifest.xml”

Nas configurações do arquivo “AndroidManifest.xml” não faremos pra-ticamente quase nada de diferente, apenas definimos todas as Atividades utilizadas. Ver listagem 08.

<?xml version=”1.0” encoding=”utf-8”?><manifest xmlns:android=”http://schemas.android.com/apk/res/android” package=”com.example.login” android:versionCode=”1” android:versionName=”1.0” >

<uses-sdk android:minSdkVersion=”19” android:targetSdkVersion=”19” />

<application

android:allowBackup=”true” android:icon=”@drawable/ic_launcher” android:label=”@string/app_name” android:theme=”@style/AppTheme” > <activity android:name=”com.example.login.MainActivity” android:label=”@string/app_name” > <intent-filter><action android:name=”android.intent.action.MAIN” /><category android:name=”android.intent.category.LAUNCHER” /> </intent-filter> </activity>

<activity android:name=”com.example.login.CadastroAtividade” android:label=”Cadastro” > <intent-filter><action android:name=”android.intent.action.MAIN” /><category android:name=”android.intent.category.LAUNCHER” /> </intent-filter> </activity> <activity android:name=”LoginAtividade” android:label=”Login do Sistema” android:screenOrientation=”portrait” android:theme=”@android:style/Theme.Dialog”> <intent-filter><action android:name=”android.intent.action.MAIN”/> </intent-filter> </activity> </application></manifest>

Page 28: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março201528

Deveremos nos atentar para o Trecho do código referente à Tela de Login do Sistema. Teremos que realizar algumas configurações para que a tela fique com um lay-out agradável para o usuário. A propriedade “android:screenOrientation” deixaremos como “portrait”. Já no “android:theme” deixaremos como “@android:style/Theme.Dialog”.

Exemplo em “Run-Time”

O resultado final poderá ser conferido na Imagem 06.

Conclusões

Pudemos aprender neste artigo uma alternativa de como deveremos proceder para criação de uma tela de Login. Procurei também ser bem claro e objetivo dando a oportunidade de implementar novas funcionalidades caso for necessário. Fiquem a vontade para baixar o arquivo de exemplo e testar em suas aplicações.

Um abraço e até o mês que vem!

Figura 06: Executando o exemplo.

[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 29: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 29

Page 30: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015

dicas the club

30

Firebird e Firedac

Nesta dica vamos demonstrar como realizar uma simples conexão no banco de dados Firebird através dos componentes do Firedac e seguindo uma estrutura semelhante com o já conhecido DBExpress.

Para iniciarmos adicione os seguintes componentes:

• FDConnection – Indicamos a conexão com nossa base de dados assim como é feito no ‘SQLConnection’, veja exemplo abaixo:

• FDCommand – Neste componente indicamos a consulta SQL

que vamos utilizar, assim como realizado no ‘SQLDataSet’, este componente se conecta automaticamente ao ‘FDConnection’ de sua aplicação mas, pode alterar manualmente na propriedade ‘Connection’.

• FDTableAdapter – Assim como o ‘DataSetProvider’ este compo-nente será responsável por realizar a conexão entre o banco de dados e a aplicação executando os comandos solicitados. Conecte seu ‘FDTableAdapter’ ao ‘FDCommand’ através da propriedade ‘SelectCommand’.

• FDMemTable – Por fim temos o componente ‘FDMemTabel’ que será o nosso ‘ClientDataSet’, nele temos praticamente todas as funcionalida-des que já conhecemos de seu predecessor, Conecte seu ‘FDMemTable’ ao ‘FDTableAdapter’ através da propriedade ‘Adapter’.

• FDPhysFBDriverLink – Este componente é responsável por conectar sua aplicação ao driver referente ao banco de dados que utiliza, ou seja, esse componente muda de banco para banco. Veja abaixo outros exemplos:

FDPhysOracleDriverLink - ;FDPhysMySQLDriverLink - .

• FDGUIxWaitCursor – Este componente é utilizado no Firedac para exibir um cursor de espera nas conexões.

Após realizar todas as configurações insira os seguintes componentes:

• DBGrid, DBNavigator, DataSource.

Vamos utiliza-los apenas para exibir os dados, veja imagem abaixo:

Page 31: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015 05

Page 32: The Club - megazine · Todo conhecimento adquirido hoje em dia é essencial para a for-mação de um bom profissional, e isto se aplica principalmente em nosso ramo de negócios

março2015