SlideShare uma empresa Scribd logo
1 de 32
Baixar para ler offline
março
2015
março
2015
março
2015
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
março
2015
04
Delphi é marca registrada da Borland International,
as demais marcas citadas são registradas
pelos seus respectivos proprietários.
Thiago Montebugnoli- Editor Chefe
thiago@theclub.com.br
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
redigiuoartigo“FastFile2.0–AplicativoLeitorparaArquivosGrandes”.
Nesta segunda versão ele implementa novas melhorias em termos de
performance dentre outros quesitos interessantes que diz respeito a
manipulaçãodedados.JáoconsultortécnicoMarlonAparecidoBran-
co Valentino continua com a saga escrevendo artigos relacionados ao
Bootstrap. Ele apresenta junto com o framework “AngularJS” uma for-
maalternativadesenvolverumatelaparacarregamentodeaplicaçõ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
Internet
http://www.theclub.com.br
Cadastro: cadastro@theclub.com.br
Suporte: suporte@theclub.com.br
Informações: info@theclub.com.br
Skype Cadastro: theclub_cadastro
Skype Suporte: theclub_linha1
theclub_linha2
theclub_linha3
www.twitter.com/theclubbr
Copyright The Club 2013
Diretor Técnico
Marcos César Silva
Diagramação
Vitor M. Rodrigues
Design
Vitor M. Rodrigues
Revisão
Denise Blair
Colunistas
Hamden Vogel
Jeferson Silva de Lima
Luciano Pimenta
Marlon Aparecido Branco Valentino
Thiago Cavalheiro Montebugnoli
Impressão e acabamento:
GRIL - Gráfica e Editora
Taquarituba-SP - Tel. (14) 3762-1345
Reprodução
A 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
março
2015
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, principalmenteseoaplicativonãoestiverhospedadoemumservidor
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
asfunçõesJavaScript,casonenhumadassoluçõesacimasolucioneoproblema
de carregamento, sugiro que acompanhe este artigo onde estarei ensinando
a fazer uma tela de pré-carregamento, utilizando a framework do Twitter o
BootstrapeoframworkdaGoogleoAngularJS,quevemcrescendonaáreade
desenvolvimento,principalmentedepoisdolançamentodaversãodoAndroid
Lollipop 5.0, onde ele é massivamente utilizado, mas enfim, vamos ao que
interessa, a solução para o mau carregamento de sua página.
Imagem01RespectivamenteoslogosdeTwitterBootstrapeAngularJSbyGoogle.
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”(aguardecarregar,poiselepodedemoraralgunssegundos),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
Scriptsnogerenciadordesoluçõeseveremosquehaveráváriosarquivoscomo
nomedeangulareemseguidaaversão,masnesteartigo,utilizaremosapenas
oangular.min.jseoangular-animate.min.js,ambossãoarquivos“minificados”
para um melhor carregamento, neste artigo irei mostrar como adicionar o
Bootstrap e AngularJS
Teladecarregamentoparaaplicaçõesweb
março
2015
06
angularJS ao seu projeto pelas nuvens, note que iremos adicionar apenas a
bibliotecaprincipalenãoopacotecompletodesuasbibliotecas,ouseja,caso
acompanhe o tópico3,seránecessárioacompanhar tambémo tópico4deste
artigoparaquenofinalsuateladepré-carregamentofuncionecorretamente.
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.
logoaparecerãováriosresultados,oprimeirodeleséabibliotecaprincipal
doangular,eaopassaromousesobreaopçãoépossívelobservarquehabilitará
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-AdicionandooAngularJSaoprojetoparaqueelecarregue
localmente.
OprimeiropassoéentrarnoarquivoBundlesConfig.cs,ondesãodeclara-
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”));
DepoisdecriaronovopacoteparaoAngularJS,váatéapáginamestrede
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.
março
2015
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.
AgoraseránecessáriocriarumarquivodeestilosparacolocarocódigoCSS
disponibilizadopelositedo“spinkit”,parafazê-lobastairatéoseuexplorador
de soluções, localizar a pasta “Content” de seu projeto e clicar com o botão
direitoemcimadamesma,iremAdddepoiscliqueemStyleSheet,damesma
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
omesmo,elocalizeoStyleBundle(pacotedeestilos)comonomedeContent/
css,eadicioneocaminhodospinner.css,bastacolocarumavírgulanafrentedo
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.
março
2015
08
OBS:Quandoestiverlendoesteartigo,provavelmenteesteprojeto
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 é
oobjetivodomesmo,eparaqueménovoemAngularJSrecomendoque
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.
ParacomeçarcriaremosumarquivoJavaScriptdentrodapastaScriptsdo
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;
});}});
março
2015
09
8- Adicionando o Script do AngularJS ao projeto pelo Bun-
dlesConfig.
Agorasalveefecheoarquivo,váatéoBundleConfig.cselocalizeocódigo
ondedeclaramosoAngularJSanteriormenteeadicioneocaminhodoarquivo
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
aberturadadiretiva(adiv),seránecessáriodeclararaclassequeutilizamosna
função angularJS que escrevemos anteriormente, e na frente a referencia do
Styleblockdonossocontainer,destaformaquandooaplicativoforcarregadoe
ocontainer(ateladecarregamento)forremovidadatela,eleautomaticamente
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
dositespinkit(fontedateladecarregamento)dentrodela,oubastarecortá-lo
março
2015
10
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>
Enfimpodemoscompilaroprojetoeverificarofuncionamento,oresultado
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-Comoalteraracordoefeitodepré-carregamentoecomo
obteracoridealatravésdo“colorpicker”(selecionadordecores)
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
peloefeito,bastaacessaroarquivospinner.cssquecriamos,encontraraclasse
ondeestádeclaradoostylebackground-color,nafrentedeleédeclaradaacor,
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áximoacorficacomaopacidadenormal(semtransparência),utilizandoesta
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.
Agoravocêdeveestarseperguntando“Paraqueserveobotãonocantoin-
feriordireito?”,aquelebotãoumrecursoparaselecionarateladoseudesktop,
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).
março
2015
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-
mentodaexibiçãodatela,nomeucaso,invertiascores,coloqueiacordologo
doVisualStudiocomoplanodefundoedeixeiadoefeitocomobranco(código
hexadecimal da cor branca é #FFF).
Paraalteraracordoplanodefundováatéapáginamestredeseuprojeto,
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:
suporte@theclub.com.br
Marlon Aparecido Branco Valentino
jovemdesenvolvedorfront-end,comconhecimentonaslingua-
gensHTML5,CSS3,JavaScript,enasframeworksjQuery,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é-carregamentoparaasuaaplicaçãoemAngularJS,etambémalgumasdicas
paraconheceresteframeworkquevemcrescendoaolongodosúltimosanos.
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!
março
2015
12
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-
mancedentreoutrosquesitosinteressantesnoquedizrespeitoamanipulaçã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;edessamaneiranegocialmentepodeterumaltocusto,degrande
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?Qualamelhorformadeabrirarquivosgrandesemostrarelesnatela?
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.
Separarprapensar,constataráqueasalternativasencontradasnainternet
sãoumtantodesanimadoras–experimenteutilizaralternativascomo“Memory
Mapping Files”, por exemplo. Sua aplicação vai lançar uma exceção do tipo
“OutOfMemory”eencerraroprograma.Demaisalternativascomoobjetosdo
tipo TStringList ou até do tipo TMemoryStream também darão o erro seme-
lhante–etefrustarão–nenhumdelesvaiabrirecarregaroarquivo. Poderão
até tentar, mas vão parar em algum ponto e abortarão o seu procedimento/
função de carregamento do arquivo.
Nossoaplicativopodedemoraratéalgunssegundosamaispraresponder,
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.
Nestarevisãodoprograma,emsuaversão2.0,muitascoisasforam
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
componenteadicionalaonossoaplicativo.Anovidadeéexplorarrecur-
sosdeextraçãodepartesviaTMemoryStreameexibi-losinteiramente
emumTListViewvirtualetambématravésdeumTClientDataSetaces-
sadoviamultithread,salvandoemumcampodotipoftBlobeindexado
– assim o arquivo pesado será aberto, lido e carregado sem nenhum
problema!Aprimeiraalternativa(TListView)éamaisrecomendávelpor
sermaisvelozemenospropensaaerrosdoqueasegunda.Oprograma
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 GHz
4. Permissão de leitura e gravação do diretório onde o arquivo se
encontra.
março
2015
13
Criação do Cenário – Primeira Alternativa
Agoravamosexplicarcomovaiseronossoambiente.Eécomoserálidoo
arquivo.Eleserálidoparteporparte–teremosumobjetochamadoStrmInput
(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–nossafunçãoNumberOfPartsToDivide)ondeporsuavezrepresenta
ototaldepartesaseremlidas,relação“tamanhooriginaldoarquivo/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=>arredondamentode1000).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-secomprimentoetamanho–termosidênticosparaaexemplificaçã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:
Base10elevadaaoexpoente(comprimentodoarquivooriginal–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.Quantomaioroarquivo,maiorotamanhodecadaparteaserdividida
(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(fil
esize))) of //convert to bytes
1: denominator := 4;
2: denominator := 8;
else
denominator :=
Round(Math.Power(10,
length(IntToStr(filesize)) - Rou
nd(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;
março
2015
14
StrmOutput.
CopyFrom(StrmInput,PartFileSi
ze);
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çãoparticulardeTList– FLineReaderList–inserindonelaaslinhas
(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
AclasseTLineReaderrepresentanossaexcelênciadesoluçãodeleiturade
cada linha do arquivo desejado. Essa leitura será feita extremamente rápida,
porserimplementadaemumaclasseTLineReaderList (TList)–ondecadaitem
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. TLineReaderListimplementaumconjuntodeTLineReader,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)parareportaràtelaoandamentodaexecuçãodestaoperação;
7. Após essa etapa todos os dados da estrutura TLineReaderList
estarão disponíveis para o nosso TListView, apresentando rapidamente sob
demandatodasasqueforemrequisitadasporeledinamicamente.Enãohaverá
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
oconteúdodoarquivodesejado–linhaalinha,armazenandooiddalinhaeo
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
threads
type
TMyObject = class
private
Counter: integer;
public
constructor Create(const
iCounter: integer);
end;
var
ThreadList: TThreadList;
// The line class definition
type
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;
março
2015
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. Apenasumathreadporvezvaigravarnaestruturadelista 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.
OobjetodeTListViewimprimiráosdadosdasleituras,linhaalinha,natela
doaplicativo,sendorenderizadodinamicamenteporumobjetodotipoTScroll-
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
UmobjetodeTListViewéumobjetoextremamenteútil.Podesecomportar
de varias formas, isto é, tem vários tipos de visualização, formatação, etc. A
lista de arquivos do MsWindowsExplorer é um objeto de TListView.
OcomponenteTListViewéumencapsulamentodocomponenteListView
doWindows.Eleémuitointeressantenoquedizrespeitoasuaflexibilidadede
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.
Porisso,suautilizaçãoémuitosatisfatória,podendosubstituircomponen-
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.
Sedesejamosmostrarummilhãoderegistros,porexemplo,vaitravar!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ínessecasotudovaimelhorar,poisnossoobjetodeTListViewapenasvai
solicitarositensquedesejamostrar,aumentandomuitoavelocidadedeapre-
sentação.IssoaconteceporqueoobjetodeTListViewvirtualnãoéproprietária
deseusitens.Elanãosabeoqueelaguardadentrodesimesma.Enaverdade
elanãoguardamesmo,quemvaiguardarvaiserumaestruturaauxiliardentro
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
momentoemquesãovisualizados–enãotodosdeumasóvez–comoseriase
fossenão-virtual(omodotradicional).Avantageméavelocidadeadmirávelde
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éumalista(coleção)deobjetos,acessívelporumíndice,ondeesteíndice
retornademaisatributosdesteobjetorelacionadodentrodela,podendocriar
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)utilizandoaindexaçãodoarrayItemsdela.Ouseja,
é 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,paradentrodenossaestruturaauxiliar(TLineReaderList)quefará
o papel de “suporte de armazenamento auxiliar” para a renderização virtual
de nosso objeto de TListView:
março
2015
16
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;
Deacordocomocódigoacima,arenderizaçãoseráfeitaautomaticamente
porqueoobjetodeTListViewsaberáoquebuscarnahoradeexibirosdados–
nemtudoémostradoaomesmotempo,mas“sobdemanda”,ouseja,amedida
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 getLineContentsFromLi
neIndex(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) + ‘ ‘ + getLin
eContentsFromLineIndex(Index);
end;
Assim sendo, a função getLineContentsFromLineIndex retorna sempre o
conteúdo atual de TLineReaderList (FLineReaderList.Items[iLine].Contents) –
chamadolinhaalinhapeloTListViewvirtual.Reparenosparâmetrosdoevento
OnData(Sender:TObject;Item:TListItem)–osegundoparâmetroéoíndiceda
linha! E ele fará referência à nossa função – chamando linha por linha – mas
nossaestruturaébaseadaemTList–entãonãohaverá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íamosemmenosdeumsegundoacompilaçãoapresentandoarenderizaçã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,
março
2015
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çõesentreaslinhasdoTListViewcomoeventoOnScrolldoTScrollbar.
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
março
2015
18
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 := Chang
eFileExt((ExtractFilePath(StrFi
lename) +
março
2015
19
IncludeTrailingPathDe
limiter(tempFolder) + ExtractFi
leName(StrFilename)),’.’+Format
(‘%.03d’,[FileNumber]));
SequentialId :=
StrToIntDef(Self.ExtractFileExt
AfterDot(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(S
trmInput,PartFileSize);
case fSelectedType of
StPartRead:
TFileReadThread.Create(False,
SequentialFile, SequentialId,
{PartFileSize,} Biblioteca.Memo
ryStreamToString(StrmOutput));
StMerge:
TFileSaveThread.Create(False,
SequentialId, Biblioteca.Memory
StreamToString(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-
menteemumobjetodeTClientDataSet,aoinvésdesergravadanaquelanossa
estrutura de apoio TLineReaderList.
Pessoalmente, prefiro a primeira opção, a que foi explicada até agora. O
TListViewsecomportamaiseficientee“seguro”narenderizaçãodaslinhasde
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–oTListViewvenceemdisparada.Entãopraqueabordareleagora?
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óriareclamaenviandoexceçõesaocompiladordeinsuficiênciadememória.
O leitor vai preferir a primeira opção, por raramente apresentará erros
de falta de memória.
ComoTListview,mesmocomestasrazõescitadasacimaaaplicaçãoainda
funciona,possivelmenteumpoucomaislento–algunssegundosamais–mas
travarjáseráalgomaisdifícildeacontecer.Omesmojánãoserápossíveldizer
comasegundaalternativa–oTClientDataSet–chamareleacadathreadnãofoi
umresultadotãosatisfatório–apromessadelertodasaspartesdeumarquivo
grandeemquestãopodefalhar.Assim,omaisseguroéaprimeiraalternativa.
Figuras 07/08/09 – Exibição do FastFile com a segunda opção escolhida – com o
objeto TClientDataSet em ação.
março
2015
20
Figuras10/11–ExibiçãodoFastFilecomasegundaopçãoescolhida–comoobjeto
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 TClientDataSet
Agilidade 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,melhoropçãoeleita:TListView!Éocomponentequelerá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-
nentedeveestaremmodovirtual,comapropriedadeOwnerDatacomoTrue.
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áoandamentodarotinapassoapassoparacertificarao
usuárioqueoFastFileestátrabalhando,comasthreadsdeleituraemsegundo
plano, para carregar o arquivo e disponibilizar ele nos objetos instanciados
(classe TListView/TClientDataSet) e assim poder lê-lo integralmente e sem
problema algum.
Oaplicativolerálinhaalinhadosarquivos(opção1)–maselenãoprocessa
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
realizaresseprocessamentodispendiosodememóriapelosmétodospadrões.
Daí nossa construção do FastFile.
Portanto, conforme eu já disse ele é um mero leitor de arquivos, porque
oleitornãovaiesperaroutrasfuncionalidadescontidasnoFastFile–claroque
muitas coisas poderiam ser acrescentadas, mas isso já assunto para outros
artigos. Sugestões são sempre bem-vindas, o programa é freeware, portanto
sinta-seavontade,boadiversãocomosfontesinclusos,apenasumacitaçãode
copyright ao meu nome e tudo está resolvido. Bons estudos e até a próxima!
suporte@theclub.com.br
Hamden Vogel
Analista 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
especializadosemDelphi. Tambémdesenvolveemoutraslinguagenscomo
C/C++, ASP, PHP e .NET.
Sobre o autor
março
2015
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
suaversão4.4poderemosimplementartécnicasmuitolegaisparaestatarefa.
No primeiro momento será criada uma classe contendo dados do usuário,
comoporexemplo:“Usuário”e“Senha”.ATeladeLoginseráherdadadeuma
“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/AndroidApplicationProject”definindoumNomeparaaaplicação,
projeto e o pacote. No meu caso foi definido como:
Application Name: Login
Project Name: Login
Package Name: com.example.login
RecomendotambémfazerousodoSDK4.4-API19,oAndroid4.4KitKat.
Ver Imagem 01.
Figura 01: Criando uma aplicação Android.
Android – Criando uma
Tela de Login
Ospróximospassosdeveremosseguirasconfiguraçõespadrõesdeprojeto.
(Nãodetalhareiestaetapapoistemosinúmerosartigosemnossarevistasobre
esteassunto).ComoprojetocriadopodemosnotarapresençadeumaActivity
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;
março
2015
22
}
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)
Respeitandoaestruturadescritaacima,deveremoscriartodososarquivos
responsáveis pelo funcionamento do projeto, ver Figura 02.
Figura 02: Estrutura do projeto.
março
2015
23
Listagem 2
1) Main_activity.xml
Nesta tela teremos apenas um botão responsável por chamar a tela de
login.Atravésdeledisparamosométodo“OnActivityResult”queserá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 {
@Override
protected void onCreate(Bundle
savedInstanceState)
{
		 super.
onCreate(savedInstanceState);
março
2015
24
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”.
@Override
protected 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=”vertic
al”
android:padding=”5dp” >
<TextView
android:id=”@+id/txtLogin”
android:layout_
width=”match_parent”
android:layout_
height=”wrap_content”
android:text=”Usuário”
android:textAppea
rance=”?android:attr/
textAppearanceMedium” />
<EditText
março
2015
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:textAppea
rance=”?android:attr/
textAppearanceMedium” />
<EditText
android:id=”@+id/edtSenha”
android:layout_
width=”match_parent”
android:layout_height =
“wrap_content”
android:ems=”10”
android:inputType=”textPas
sword” />
<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();
}
março
2015
26
Listagem 7
Ométodo“MensagemInformativa”recebecomoparâmetroumavariá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
comoporexemplo:“setTitle”(Inserirtítulonacaixadediálogo),“SetMessage”
(Mensagemdisparada),“setPositiveButton”(BotãoOk)e“setCancelable”(in-
dicandoquenãopossuiobotãocancelar)eométodo“show”(paracarregá-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();
}
}
Ométodo“Login”recebecomoparâmetroaprópriaView,sendodisparado
noevento“OnClick”doBotão.Deveremosinstanciaraclasse“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”>
março
2015
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:textApp
earance=”?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:screenOri
entation=”portrait”
android:theme=”@
android:style/Theme.Dialog”>
<intent-filter>
<action android:name=”android.
intent.action.MAIN”/>
</intent-filter>
</activity>
</application>
</manifest>
março
2015
28
DeveremosnosatentarparaoTrechodocódigoreferenteàTeladeLogindo
Sistema.Teremosquerealizaralgumasconfiguraçõesparaqueatelafiquecom
umlay-outagradávelparaousuário.Apropriedade“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.
thiago@theclub.com.br
Thiago Cavalheiro Montebugnoli
adora 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-MicrosoftCertifiedTechnologySpecialist,MCAD-MicrosoftCertifiedApplicationDeveloper
e MCSD - Microsoft Certified Solution Developer.
Sobre o autor
março
2015
29
março
2015
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çãoexecutandooscomandossolicitados.Conecteseu‘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 –Estecomponenteéresponsávelporconectar
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:
março
2015
05
março
2015

Mais conteúdo relacionado

Semelhante a 1503 - Revista - Angular.pdf

INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
clesiojunior
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI Android
Vinícius Thiengo
 
Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)
marcondes da luz barros
 
Estrutura de um Front-End eficiente (para iniciantes)
Estrutura de um Front-End eficiente (para iniciantes)Estrutura de um Front-End eficiente (para iniciantes)
Estrutura de um Front-End eficiente (para iniciantes)
Sérgio Vilar
 

Semelhante a 1503 - Revista - Angular.pdf (20)

Bada
BadaBada
Bada
 
Parse Push Notification - O Lado negro da força
Parse Push Notification - O Lado negro da forçaParse Push Notification - O Lado negro da força
Parse Push Notification - O Lado negro da força
 
Dreamweaver cs5
Dreamweaver cs5Dreamweaver cs5
Dreamweaver cs5
 
Introdução ao AngularJS - Minicurso
Introdução ao AngularJS - MinicursoIntrodução ao AngularJS - Minicurso
Introdução ao AngularJS - Minicurso
 
Blogger rapido
Blogger rapidoBlogger rapido
Blogger rapido
 
Como criar um plugin sem ser desenvolvedor
Como criar um plugin sem ser desenvolvedorComo criar um plugin sem ser desenvolvedor
Como criar um plugin sem ser desenvolvedor
 
Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações Android
 
INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
INTEROPERABILIDADE ENTRE SISTEMAS DE INFORMAÇÃO HETEROGÊNEOS NA PRÁTICA – NO ...
 
1401 - Revista - Android.pdf
1401 - Revista - Android.pdf1401 - Revista - Android.pdf
1401 - Revista - Android.pdf
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI Android
 
Introdução à Programação Web com Angular
Introdução à Programação Web com AngularIntrodução à Programação Web com Angular
Introdução à Programação Web com Angular
 
Revista programar 12
Revista programar 12Revista programar 12
Revista programar 12
 
2° Codelab - Por onde começar com AngularJS
2° Codelab  - Por onde começar com AngularJS2° Codelab  - Por onde começar com AngularJS
2° Codelab - Por onde começar com AngularJS
 
Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)Atividade integradora mod iii tec informatica 2016(1)
Atividade integradora mod iii tec informatica 2016(1)
 
Estrutura de um Front-End eficiente (para iniciantes)
Estrutura de um Front-End eficiente (para iniciantes)Estrutura de um Front-End eficiente (para iniciantes)
Estrutura de um Front-End eficiente (para iniciantes)
 
Ebook - Processo de Otimização de Sites WordPress
Ebook - Processo de Otimização de Sites WordPressEbook - Processo de Otimização de Sites WordPress
Ebook - Processo de Otimização de Sites WordPress
 
CORE WEB VITALS E WORDPRESS
CORE WEB VITALS E WORDPRESSCORE WEB VITALS E WORDPRESS
CORE WEB VITALS E WORDPRESS
 
WordCamp Floripa 2021 - Daniel - Core web vitals e WordPress
WordCamp Floripa 2021 - Daniel  - Core web vitals e WordPressWordCamp Floripa 2021 - Daniel  - Core web vitals e WordPress
WordCamp Floripa 2021 - Daniel - Core web vitals e WordPress
 
Adobe Digital Publishing Solution
Adobe Digital Publishing Solution Adobe Digital Publishing Solution
Adobe Digital Publishing Solution
 
APIs gerenciadas de ponta a ponta - construção
APIs gerenciadas de ponta a ponta - construçãoAPIs gerenciadas de ponta a ponta - construção
APIs gerenciadas de ponta a ponta - construção
 

1503 - Revista - Angular.pdf

  • 3. março 2015 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
  • 4. março 2015 04 Delphi é marca registrada da Borland International, as demais marcas citadas são registradas pelos seus respectivos proprietários. Thiago Montebugnoli- Editor Chefe thiago@theclub.com.br 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 redigiuoartigo“FastFile2.0–AplicativoLeitorparaArquivosGrandes”. Nesta segunda versão ele implementa novas melhorias em termos de performance dentre outros quesitos interessantes que diz respeito a manipulaçãodedados.JáoconsultortécnicoMarlonAparecidoBran- co Valentino continua com a saga escrevendo artigos relacionados ao Bootstrap. Ele apresenta junto com o framework “AngularJS” uma for- maalternativadesenvolverumatelaparacarregamentodeaplicaçõ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 Internet http://www.theclub.com.br Cadastro: cadastro@theclub.com.br Suporte: suporte@theclub.com.br Informações: info@theclub.com.br Skype Cadastro: theclub_cadastro Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3 www.twitter.com/theclubbr Copyright The Club 2013 Diretor Técnico Marcos César Silva Diagramação Vitor M. Rodrigues Design Vitor M. Rodrigues Revisão Denise Blair Colunistas Hamden Vogel Jeferson Silva de Lima Luciano Pimenta Marlon Aparecido Branco Valentino Thiago Cavalheiro Montebugnoli Impressão e acabamento: GRIL - Gráfica e Editora Taquarituba-SP - Tel. (14) 3762-1345 Reprodução A 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
  • 5. março 2015 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, principalmenteseoaplicativonãoestiverhospedadoemumservidor 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 asfunçõesJavaScript,casonenhumadassoluçõesacimasolucioneoproblema de carregamento, sugiro que acompanhe este artigo onde estarei ensinando a fazer uma tela de pré-carregamento, utilizando a framework do Twitter o BootstrapeoframworkdaGoogleoAngularJS,quevemcrescendonaáreade desenvolvimento,principalmentedepoisdolançamentodaversãodoAndroid Lollipop 5.0, onde ele é massivamente utilizado, mas enfim, vamos ao que interessa, a solução para o mau carregamento de sua página. Imagem01RespectivamenteoslogosdeTwitterBootstrapeAngularJSbyGoogle. 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”(aguardecarregar,poiselepodedemoraralgunssegundos),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 Scriptsnogerenciadordesoluçõeseveremosquehaveráváriosarquivoscomo nomedeangulareemseguidaaversão,masnesteartigo,utilizaremosapenas oangular.min.jseoangular-animate.min.js,ambossãoarquivos“minificados” para um melhor carregamento, neste artigo irei mostrar como adicionar o Bootstrap e AngularJS Teladecarregamentoparaaplicaçõesweb
  • 6. março 2015 06 angularJS ao seu projeto pelas nuvens, note que iremos adicionar apenas a bibliotecaprincipalenãoopacotecompletodesuasbibliotecas,ouseja,caso acompanhe o tópico3,seránecessárioacompanhar tambémo tópico4deste artigoparaquenofinalsuateladepré-carregamentofuncionecorretamente. 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. logoaparecerãováriosresultados,oprimeirodeleséabibliotecaprincipal doangular,eaopassaromousesobreaopçãoépossívelobservarquehabilitará 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-AdicionandooAngularJSaoprojetoparaqueelecarregue localmente. OprimeiropassoéentrarnoarquivoBundlesConfig.cs,ondesãodeclara- 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”)); DepoisdecriaronovopacoteparaoAngularJS,váatéapáginamestrede 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.
  • 7. março 2015 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. AgoraseránecessáriocriarumarquivodeestilosparacolocarocódigoCSS disponibilizadopelositedo“spinkit”,parafazê-lobastairatéoseuexplorador de soluções, localizar a pasta “Content” de seu projeto e clicar com o botão direitoemcimadamesma,iremAdddepoiscliqueemStyleSheet,damesma 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 omesmo,elocalizeoStyleBundle(pacotedeestilos)comonomedeContent/ css,eadicioneocaminhodospinner.css,bastacolocarumavírgulanafrentedo 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.
  • 8. março 2015 08 OBS:Quandoestiverlendoesteartigo,provavelmenteesteprojeto 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 é oobjetivodomesmo,eparaqueménovoemAngularJSrecomendoque 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. ParacomeçarcriaremosumarquivoJavaScriptdentrodapastaScriptsdo 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; });}});
  • 9. março 2015 09 8- Adicionando o Script do AngularJS ao projeto pelo Bun- dlesConfig. Agorasalveefecheoarquivo,váatéoBundleConfig.cselocalizeocódigo ondedeclaramosoAngularJSanteriormenteeadicioneocaminhodoarquivo 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 aberturadadiretiva(adiv),seránecessáriodeclararaclassequeutilizamosna função angularJS que escrevemos anteriormente, e na frente a referencia do Styleblockdonossocontainer,destaformaquandooaplicativoforcarregadoe ocontainer(ateladecarregamento)forremovidadatela,eleautomaticamente 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 dositespinkit(fontedateladecarregamento)dentrodela,oubastarecortá-lo
  • 10. março 2015 10 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> Enfimpodemoscompilaroprojetoeverificarofuncionamento,oresultado 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-Comoalteraracordoefeitodepré-carregamentoecomo obteracoridealatravésdo“colorpicker”(selecionadordecores) 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 peloefeito,bastaacessaroarquivospinner.cssquecriamos,encontraraclasse ondeestádeclaradoostylebackground-color,nafrentedeleédeclaradaacor, 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áximoacorficacomaopacidadenormal(semtransparência),utilizandoesta 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. Agoravocêdeveestarseperguntando“Paraqueserveobotãonocantoin- feriordireito?”,aquelebotãoumrecursoparaselecionarateladoseudesktop, 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).
  • 11. março 2015 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- mentodaexibiçãodatela,nomeucaso,invertiascores,coloqueiacordologo doVisualStudiocomoplanodefundoedeixeiadoefeitocomobranco(código hexadecimal da cor branca é #FFF). Paraalteraracordoplanodefundováatéapáginamestredeseuprojeto, 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: suporte@theclub.com.br Marlon Aparecido Branco Valentino jovemdesenvolvedorfront-end,comconhecimentonaslingua- gensHTML5,CSS3,JavaScript,enasframeworksjQuery,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é-carregamentoparaasuaaplicaçãoemAngularJS,etambémalgumasdicas paraconheceresteframeworkquevemcrescendoaolongodosúltimosanos. 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!
  • 12. março 2015 12 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- mancedentreoutrosquesitosinteressantesnoquedizrespeitoamanipulaçã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;edessamaneiranegocialmentepodeterumaltocusto,degrande 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?Qualamelhorformadeabrirarquivosgrandesemostrarelesnatela? 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. Separarprapensar,constataráqueasalternativasencontradasnainternet sãoumtantodesanimadoras–experimenteutilizaralternativascomo“Memory Mapping Files”, por exemplo. Sua aplicação vai lançar uma exceção do tipo “OutOfMemory”eencerraroprograma.Demaisalternativascomoobjetosdo tipo TStringList ou até do tipo TMemoryStream também darão o erro seme- lhante–etefrustarão–nenhumdelesvaiabrirecarregaroarquivo. Poderão até tentar, mas vão parar em algum ponto e abortarão o seu procedimento/ função de carregamento do arquivo. Nossoaplicativopodedemoraratéalgunssegundosamaispraresponder, 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. Nestarevisãodoprograma,emsuaversão2.0,muitascoisasforam 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 componenteadicionalaonossoaplicativo.Anovidadeéexplorarrecur- sosdeextraçãodepartesviaTMemoryStreameexibi-losinteiramente emumTListViewvirtualetambématravésdeumTClientDataSetaces- sadoviamultithread,salvandoemumcampodotipoftBlobeindexado – assim o arquivo pesado será aberto, lido e carregado sem nenhum problema!Aprimeiraalternativa(TListView)éamaisrecomendávelpor sermaisvelozemenospropensaaerrosdoqueasegunda.Oprograma 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 GHz 4. Permissão de leitura e gravação do diretório onde o arquivo se encontra.
  • 13. março 2015 13 Criação do Cenário – Primeira Alternativa Agoravamosexplicarcomovaiseronossoambiente.Eécomoserálidoo arquivo.Eleserálidoparteporparte–teremosumobjetochamadoStrmInput (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–nossafunçãoNumberOfPartsToDivide)ondeporsuavezrepresenta ototaldepartesaseremlidas,relação“tamanhooriginaldoarquivo/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=>arredondamentode1000).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-secomprimentoetamanho–termosidênticosparaaexemplificaçã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: Base10elevadaaoexpoente(comprimentodoarquivooriginal–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.Quantomaioroarquivo,maiorotamanhodecadaparteaserdividida (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(fil esize))) of //convert to bytes 1: denominator := 4; 2: denominator := 8; else denominator := Round(Math.Power(10, length(IntToStr(filesize)) - Rou nd(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;
  • 14. março 2015 14 StrmOutput. CopyFrom(StrmInput,PartFileSi ze); 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çãoparticulardeTList– FLineReaderList–inserindonelaaslinhas (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 AclasseTLineReaderrepresentanossaexcelênciadesoluçãodeleiturade cada linha do arquivo desejado. Essa leitura será feita extremamente rápida, porserimplementadaemumaclasseTLineReaderList (TList)–ondecadaitem 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. TLineReaderListimplementaumconjuntodeTLineReader,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)parareportaràtelaoandamentodaexecuçãodestaoperação; 7. Após essa etapa todos os dados da estrutura TLineReaderList estarão disponíveis para o nosso TListView, apresentando rapidamente sob demandatodasasqueforemrequisitadasporeledinamicamente.Enãohaverá 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 oconteúdodoarquivodesejado–linhaalinha,armazenandooiddalinhaeo 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 threads type TMyObject = class private Counter: integer; public constructor Create(const iCounter: integer); end; var ThreadList: TThreadList; // The line class definition type 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;
  • 15. março 2015 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. Apenasumathreadporvezvaigravarnaestruturadelista 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. OobjetodeTListViewimprimiráosdadosdasleituras,linhaalinha,natela doaplicativo,sendorenderizadodinamicamenteporumobjetodotipoTScroll- 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 UmobjetodeTListViewéumobjetoextremamenteútil.Podesecomportar de varias formas, isto é, tem vários tipos de visualização, formatação, etc. A lista de arquivos do MsWindowsExplorer é um objeto de TListView. OcomponenteTListViewéumencapsulamentodocomponenteListView doWindows.Eleémuitointeressantenoquedizrespeitoasuaflexibilidadede 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. Porisso,suautilizaçãoémuitosatisfatória,podendosubstituircomponen- 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. Sedesejamosmostrarummilhãoderegistros,porexemplo,vaitravar!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ínessecasotudovaimelhorar,poisnossoobjetodeTListViewapenasvai solicitarositensquedesejamostrar,aumentandomuitoavelocidadedeapre- sentação.IssoaconteceporqueoobjetodeTListViewvirtualnãoéproprietária deseusitens.Elanãosabeoqueelaguardadentrodesimesma.Enaverdade elanãoguardamesmo,quemvaiguardarvaiserumaestruturaauxiliardentro 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 momentoemquesãovisualizados–enãotodosdeumasóvez–comoseriase fossenão-virtual(omodotradicional).Avantageméavelocidadeadmirávelde 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éumalista(coleção)deobjetos,acessívelporumíndice,ondeesteíndice retornademaisatributosdesteobjetorelacionadodentrodela,podendocriar 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)utilizandoaindexaçãodoarrayItemsdela.Ouseja, é 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,paradentrodenossaestruturaauxiliar(TLineReaderList)quefará o papel de “suporte de armazenamento auxiliar” para a renderização virtual de nosso objeto de TListView:
  • 16. março 2015 16 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; Deacordocomocódigoacima,arenderizaçãoseráfeitaautomaticamente porqueoobjetodeTListViewsaberáoquebuscarnahoradeexibirosdados– nemtudoémostradoaomesmotempo,mas“sobdemanda”,ouseja,amedida 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 getLineContentsFromLi neIndex(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) + ‘ ‘ + getLin eContentsFromLineIndex(Index); end; Assim sendo, a função getLineContentsFromLineIndex retorna sempre o conteúdo atual de TLineReaderList (FLineReaderList.Items[iLine].Contents) – chamadolinhaalinhapeloTListViewvirtual.Reparenosparâmetrosdoevento OnData(Sender:TObject;Item:TListItem)–osegundoparâmetroéoíndiceda linha! E ele fará referência à nossa função – chamando linha por linha – mas nossaestruturaébaseadaemTList–entãonãohaverá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íamosemmenosdeumsegundoacompilaçãoapresentandoarenderizaçã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,
  • 17. março 2015 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çõesentreaslinhasdoTListViewcomoeventoOnScrolldoTScrollbar. 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
  • 18. março 2015 18 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 := Chang eFileExt((ExtractFilePath(StrFi lename) +
  • 19. março 2015 19 IncludeTrailingPathDe limiter(tempFolder) + ExtractFi leName(StrFilename)),’.’+Format (‘%.03d’,[FileNumber])); SequentialId := StrToIntDef(Self.ExtractFileExt AfterDot(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(S trmInput,PartFileSize); case fSelectedType of StPartRead: TFileReadThread.Create(False, SequentialFile, SequentialId, {PartFileSize,} Biblioteca.Memo ryStreamToString(StrmOutput)); StMerge: TFileSaveThread.Create(False, SequentialId, Biblioteca.Memory StreamToString(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- menteemumobjetodeTClientDataSet,aoinvésdesergravadanaquelanossa estrutura de apoio TLineReaderList. Pessoalmente, prefiro a primeira opção, a que foi explicada até agora. O TListViewsecomportamaiseficientee“seguro”narenderizaçãodaslinhasde 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–oTListViewvenceemdisparada.Entãopraqueabordareleagora? 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óriareclamaenviandoexceçõesaocompiladordeinsuficiênciadememória. O leitor vai preferir a primeira opção, por raramente apresentará erros de falta de memória. ComoTListview,mesmocomestasrazõescitadasacimaaaplicaçãoainda funciona,possivelmenteumpoucomaislento–algunssegundosamais–mas travarjáseráalgomaisdifícildeacontecer.Omesmojánãoserápossíveldizer comasegundaalternativa–oTClientDataSet–chamareleacadathreadnãofoi umresultadotãosatisfatório–apromessadelertodasaspartesdeumarquivo grandeemquestãopodefalhar.Assim,omaisseguroéaprimeiraalternativa. Figuras 07/08/09 – Exibição do FastFile com a segunda opção escolhida – com o objeto TClientDataSet em ação.
  • 20. março 2015 20 Figuras10/11–ExibiçãodoFastFilecomasegundaopçãoescolhida–comoobjeto 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 TClientDataSet Agilidade 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,melhoropçãoeleita:TListView!Éocomponentequelerá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- nentedeveestaremmodovirtual,comapropriedadeOwnerDatacomoTrue. 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áoandamentodarotinapassoapassoparacertificarao usuárioqueoFastFileestátrabalhando,comasthreadsdeleituraemsegundo plano, para carregar o arquivo e disponibilizar ele nos objetos instanciados (classe TListView/TClientDataSet) e assim poder lê-lo integralmente e sem problema algum. Oaplicativolerálinhaalinhadosarquivos(opção1)–maselenãoprocessa 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 realizaresseprocessamentodispendiosodememóriapelosmétodospadrões. Daí nossa construção do FastFile. Portanto, conforme eu já disse ele é um mero leitor de arquivos, porque oleitornãovaiesperaroutrasfuncionalidadescontidasnoFastFile–claroque muitas coisas poderiam ser acrescentadas, mas isso já assunto para outros artigos. Sugestões são sempre bem-vindas, o programa é freeware, portanto sinta-seavontade,boadiversãocomosfontesinclusos,apenasumacitaçãode copyright ao meu nome e tudo está resolvido. Bons estudos e até a próxima! suporte@theclub.com.br Hamden Vogel Analista 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 especializadosemDelphi. Tambémdesenvolveemoutraslinguagenscomo C/C++, ASP, PHP e .NET. Sobre o autor
  • 21. março 2015 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 suaversão4.4poderemosimplementartécnicasmuitolegaisparaestatarefa. No primeiro momento será criada uma classe contendo dados do usuário, comoporexemplo:“Usuário”e“Senha”.ATeladeLoginseráherdadadeuma “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/AndroidApplicationProject”definindoumNomeparaaaplicação, projeto e o pacote. No meu caso foi definido como: Application Name: Login Project Name: Login Package Name: com.example.login RecomendotambémfazerousodoSDK4.4-API19,oAndroid4.4KitKat. Ver Imagem 01. Figura 01: Criando uma aplicação Android. Android – Criando uma Tela de Login Ospróximospassosdeveremosseguirasconfiguraçõespadrõesdeprojeto. (Nãodetalhareiestaetapapoistemosinúmerosartigosemnossarevistasobre esteassunto).ComoprojetocriadopodemosnotarapresençadeumaActivity 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;
  • 22. março 2015 22 } 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) Respeitandoaestruturadescritaacima,deveremoscriartodososarquivos responsáveis pelo funcionamento do projeto, ver Figura 02. Figura 02: Estrutura do projeto.
  • 23. março 2015 23 Listagem 2 1) Main_activity.xml Nesta tela teremos apenas um botão responsável por chamar a tela de login.Atravésdeledisparamosométodo“OnActivityResult”queserá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 { @Override protected void onCreate(Bundle savedInstanceState) { super. onCreate(savedInstanceState);
  • 24. março 2015 24 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”. @Override protected 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=”vertic al” android:padding=”5dp” > <TextView android:id=”@+id/txtLogin” android:layout_ width=”match_parent” android:layout_ height=”wrap_content” android:text=”Usuário” android:textAppea rance=”?android:attr/ textAppearanceMedium” /> <EditText
  • 25. março 2015 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:textAppea rance=”?android:attr/ textAppearanceMedium” /> <EditText android:id=”@+id/edtSenha” android:layout_ width=”match_parent” android:layout_height = “wrap_content” android:ems=”10” android:inputType=”textPas sword” /> <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(); }
  • 26. março 2015 26 Listagem 7 Ométodo“MensagemInformativa”recebecomoparâmetroumavariá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 comoporexemplo:“setTitle”(Inserirtítulonacaixadediálogo),“SetMessage” (Mensagemdisparada),“setPositiveButton”(BotãoOk)e“setCancelable”(in- dicandoquenãopossuiobotãocancelar)eométodo“show”(paracarregá-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(); } } Ométodo“Login”recebecomoparâmetroaprópriaView,sendodisparado noevento“OnClick”doBotão.Deveremosinstanciaraclasse“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”>
  • 27. março 2015 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:textApp earance=”?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:screenOri entation=”portrait” android:theme=”@ android:style/Theme.Dialog”> <intent-filter> <action android:name=”android. intent.action.MAIN”/> </intent-filter> </activity> </application> </manifest>
  • 28. março 2015 28 DeveremosnosatentarparaoTrechodocódigoreferenteàTeladeLogindo Sistema.Teremosquerealizaralgumasconfiguraçõesparaqueatelafiquecom umlay-outagradávelparaousuário.Apropriedade“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. thiago@theclub.com.br Thiago Cavalheiro Montebugnoli adora 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-MicrosoftCertifiedTechnologySpecialist,MCAD-MicrosoftCertifiedApplicationDeveloper e MCSD - Microsoft Certified Solution Developer. Sobre o autor
  • 30. março 2015 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çãoexecutandooscomandossolicitados.Conecteseu‘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 –Estecomponenteéresponsávelporconectar 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: