The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o...

32
junho 2015

Transcript of The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o...

Page 1: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015

Page 2: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015

Page 3: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 03

15

Índice

Editorial

04

08

Autor: Hamden Vogel

05

Autor: Marlon Aparecido Branco Valentino

21

Linguagem C# - Trabalhando com Threads em Windows FormsAutor: Thiago C. Montebugnoli

Autor: Luciano Pimenta Dicas The Club

28

JavaScript - 4 Dicas rápidas para melhorar a qualidade do seu código!

Novo FastFile 3.0 – Lendo arquivos grandes – 2GB pra frente

Integração Android e Facebook - Parte II

Page 4: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201504

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

pelos seus respectivos proprietários.

Thiago Montebugnoli - Editor [email protected]

Caro amigo,

Já atingimos a metade do ano de 2015 e como diziam uns e outros o tempo passa e o tempo voa. A revista deste mês de Junho será composta de diversos tipos de assuntos e linguagens. Trabalharemos com o Android, Delphi, Javascript e C#.

Começando com nosso colunista Luciano Pimenta, ele escreve a última parte do artigo “Facebook e Android”. Neste artigo ele utiliza a segunda versão de sua API, demonstrando como interagir com essa rede social, retornando a listagem de amigos. Esta dica se torna importante para todos os desenvolvedores que desejam implementar estes recursos em seus aplicativos. Nosso colaborador mensal Ha-mden Vogel continua escrevendo sobre temas relacionados a leitura de arquivos, com o título: “FileReader – lendo bytes e frases sem carregar todo o arquivo”. Ele apresenta soluções para os estouros de memórias ocasionados frequentemente quando realizamos este tipo de leitura. Faz o uso da classe herdeira de “Tstream”, denominada “TgpHugeFileStream”. Esta classe open-source tem boa capacidade de resposta para arquivos grandes, pois foi designada especialmente para este fim. Já nosso consultor técnico Marlon Aparecido Branco Valentino abordou algu-mas dicas sobre Javascript, como por exemplo: o uso dos operadores lógicos, de comparação, Expressão de Função Imediatamente Invocada, entre outras coisas. Para finallizar a seção de artigos eu redigi um tema relacionado a Linguagem C#, como devemos trabalhar com Threads em Windows Forms. Procurei abranger os construtores, métodos e propriedades da classe “Thread” seguindo alguns exemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para o usuário.

Não podemos esquecer de nossa seção de Dicas, sempre recheada dos me-lhores macetes encontrados geralmente em nosso suporte técnico.

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

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

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

Internethttp://www.theclub.com.br

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

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club 2013

Diretor TécnicoMarcos César Silva

DiagramaçãoVitor M. Rodrigues

DesignVitor M. Rodrigues

RevisãoDenise Blair

ColunistasHamden Vogel

Jeferson Silva de LimaLuciano Pimenta

Marlon Aparecido Branco ValentinoThiago Cavalheiro Montebugnoli

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

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

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

Editorial

Page 5: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 05

Introdução

O objetivo deste artigo é ajudar os desenvolvedores iniciantes e avançados em JavaScript também caso ainda não conheçam as técnicas presentes nele que irão ajuda-lo a melhorar suas técnicas de programação, consequentemente a qualidade do seu código vai melhorar e o seu trabalho se tornará mais ágil no dia a dia. Muitos desenvolvedores avançados já utilizam estas técnicas, e em algumas páginas você também irá aprender a se beneficiar delas.

1- Os poderosos operadores lógicos de JavaScript &&(e) e ||(ou)

Um dos pontos positivos do JavaScript são seus operadores lógicos, tanto && e ||, são dois operadores muito legais, pois não funcionam como as linguagens C++ e Java que retornam valores booleanos, já em JavaScript as coisas ficam mais interessantes, nele && e || retornam os últimos valores avaliados. Observe o código a seguir:

function meDeChocolates(quantidade){ if(quantidade){

return quantidade; } else{ return 1; }}

O código apresentado é bem simples pois ele retorna o número de chocolates solicitados, se o valor de “quantidade” for falso, ele me retorna 1 chocolate apenas que no caso será o valor verdadeiro, agora se um fosse dado o valor 5 ao parâmetro(argumento) “quantidade” ele me retornará o valor de 5 chocolates, agora vamos escrever a mesma operação de uma maneira mais fácil, observe o seguinte código:

function meDeChocolates(quantidade){ return quantidade || 1;}

Neste caso, o operador ||(ou) irá avaliar o primeiro valor, se ele for falso, então o JavaScript irá avaliar o próximo valor. Logo se nenhum valor verdadeiro for dado para o parâmetro(argumento) “quantidade” o JavaScript irá retornar o valor 1 como valor verdadeiro.

OBS: null(valor nulo), false(falso), 0(zero), undefined(indefinido), NaN(not a number – não é um numero) e “”(string vázia), todos estes valores são considerados falsos. Qualquer outro valor é considerado verdadeiro.

JavaScript – 4 Dicas rápi-das para melhorar a qualidade do seu código!

Page 6: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201506

Agora se você quiser que apenas pessoas que não tenham diabetes ganhem chocolate, é possível utilizar os operadores lógicos (&& e ||) como no código abaixo:

function meDeChocolates(diabetico, quantidade){ return (diabetico === false) && (quantidade || 1 );}

Ao invés de utilizar um if e else, como é exemplificado no código abaixo:

function meDeChocolates(diabetico, quantidade){ if(diabetico === false){ return quantidade || 1;}}

Ambas os códigos a cima tem a mesma lógica e fazem a mesma coisa, agora explicando melhor a lógica, caso você não tenha entendido, nele se o parâmetro (ou argumento) “diabetico”, que é dado a função meDeChocolate, for verdadei-ro o JavaScript nem irá avaliar o próximo valor, então a nossa função retornará um valor verdadeiro (neste caso nenhum chocolate), agora se “diabetico” falso ele irá avaliar o próximo valor, que será o parâmetro(argumento) “quantidade”, então caso “quantidade” seja falso, JavaScript retornará 1 chocolate apenas.

2- Utilizeosoperadoresde comparação===(iguala)e==!(diferentede)aoinvésde==e=!.

Esta é uma dica bem rápida, falando sobre a utilização dos operadores == e =!, eles fazem a conversão automática do tipos, utilize-os caso necessário, agora === e ==! irão considerar tanto valor quanto tipo e não irá fazer nenhuma conversão automática do tipo. Sendo assim, para fazer a comparação de igual ou não diferente é mais viável utilizar === e ==!, observe o exemplo abaixo:

666 == ‘666’ //retorna verdadeiro, pois converte 666 de integer para string a ‘666’.666 === ’666’ //retorna falso, porque ‘666’ é uma string.666 === 666 //retorna verdadeiro, porque 666 é integer.

3- Utilizeo StrictMode(Modoestrito) quandoestiverprogramandoemJavaScript

Este modo foi introduzido no ECMA 5(Que seria a versão do JavaS-cript – de uma forma leiga). Ele permite que você coloque uma função ou um script inteiro operando em Strict Mode(modo estrito), ao utilizar este modo você tem os seguintes benefícios:

3.1 – Os erros do JavaScript deixam de ser silenciosos, e começam a aparecer mais explicitamente, desta forma eles podem ser rapidamente identificados e corrigidos;

3.2 – Quando seu código realiza ações consideradas inseguras ele exibe exceptions(excessões).

3.3 – Em alguns casos o código que utiliza o Strict Mode(modo estrito) é executado mais rapidamente do que um código que não o utiliza.

Para utilizar o Strict mode apenas escreva em seu script ou função a

linha ‘use strict’, desta forma o todo o código abaixo dele passa a funcionar no modo estrito, observe o exemplo abaixo de sua utilização dentro de uma <script> tag de HTML:

<script type=text/javascript> ‘use strict’ // Código em modo estrito(strict mode) vai aqui...</script>

Ou também, dentro de uma função:

function modoEstrito(){ ‘use strict’ //Esta é uma função em Strict mode...}

O BS: E ste mo d o j á é s u p o r tad o n o s p r i n c i p a i s navegadores(IE,Firefox, Google Chrome, Opera, Safari, etc), em suas versões mais atualizadas.

4- ComosebeneficiardopoderdeImmediatelyInvokedFunctionsExpressions.

Você deve estar se perguntando o que significa Imimediately Invoked Functions Expressions(Sigla IIFE pronunciado “Iffy”, como WiFi só que sem o W), a tradução fica Expressão de Função Imediatamente Invocada, ou seja uma função que é declarada e que executa sozinha, observe a sintaxe do IIFE:

Page 7: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 07

(function(quantidade){ return quantidade || 1; })(3);// Passa o valor 3 para o parâmetro(argumento) “quantidade”

O exemplo á cima exemplifica uma função que é declarada e automa-ticamente chamada em tempo de execução, nela a função recebe como parâmetro(argumento) “quantidade”, e no final da do código da função, é passado o valor de 5 no parâmetro “quantidade” da função.

4.1-Comoelafunciona?

O par de parênteses que cerca a função a transformam em uma Expressão de Função ou Expressão de Variável, dessa forma ao invés de ser uma função com anônima (significa que não foi dado nenhum nome a função) em um es-copo global (ou onde quer que tenha sido declarada), agora é uma expressão de função sem nome, logo ela é uma Expressão de Função Imediatamente Invocada(IIFE), que é executada apenas uma vez já que ela não tem nome, agora se fosse dado um nome a função como no exemplo abaixo, será possível chama-la mais de uma vez:

(ovosPascoa = function(idade, quantidade){

return (idade < 18) && (quantidade || 1);})();ovosPascoa(10, 3);

OBS: Não é permitido o uso de “var” dentro dos parênteses (você terá um erro de sintaxe caso a utilize).

A função “ovosPascoa” tem os parâmetros( ou argumentos) “idade” e “quantidade”, e ela retorna um valor falso caso idade seja menor que 18 anos, ou seja, nenhum ovo de páscoa, note utilizei a mesma lógica da dica anterior, no código a cima foi passada a idade como 10 anos e a quantidade 3, sendo assim a criança ganhará 3 ovos de páscoa. Como esta função possui um nome, é possível chama-la mais de uma vez.

Conclusão

Este artigo poderia ter milhares de dicas de JavaScript, pois há milhares delas por aí, coloquei apenas 4 delas, mas pretendo voltar com mais algumas no próximo artigo. Dicas como essas são valiosas quando você procura melhorar a qualidade do seu código, deixando ele mais enxuto.

[email protected]

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

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

Sobre o autor

Page 8: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201508

Houve tempo em que carregar arquivos era tranquilo, de uma forma simples e direta, aproveitando as classes tradicionais do Delphi como TFileStream, TextFile, etc – onde as confi-gurações de hardware e a quantidade de registros aparen-temente funcionavam muito bem entre si – a memória era

difícil de estourar – os métodos readln, eof faziam seu trabalho muito bem para arquivos de pequeno e médio porte – e com esse loop tudo estava resolvido; popular um objeto do tipo TMemo era até rápido e não onerava as aplicações.

Porém os arquivos cresceram de tamanho; aplicações tornaram-se mais exigentes em hardware; regras negociais evoluíram; as tecnologias também evoluíram; enfim; nem sempre será a melhor alternativa carregar um arquivo texto e “printar” ele todo nos componentes da VCL – questão óbvia é estouro de memória devido ao fato do alto volume de bytes. E a questão toda a que podemos chegar é carregar em partes ou em alguma estrutura que alimente a memória “por trás” da VCL – exatamente como a renderização virtual nos objetos – como em um objeto do tipo TListView, bem explicado na edição anterior. Mas agora não queremos carregar mais tudo – nem tudo pode ser necessário – o usuário poderá pesquisar algumas linhas do seu conteúdo – sem mais carregar tudo de uma vez – pois se a questão é verificar algumas linhas, não precisamos mais neste caso abrir ele, mostrando todas as suas linhas. A questão agora é economia de tempo e memória.

Podemos sempre abrir qualquer arquivo texto, sem problema algum. A questão aqui agora é obter algumas linhas dele, a partir de quantos bytes, até quantos bytes (intervalo de pesquisa), quantidade máxima de caracteres a pesquisar e quantidade máxima de linhas retornadas. O foco deste artigo é esse – e implementamos a solução batizada de “FileReader”, referência adotada a partir de agora até o final desta edição. Boa leitura !

A implementação da classe TGpHugeFileStream para o filtro de bytes pesquisados

A classe eleita para a manipulação dos bytes, herdeira de TStream e efi-cientemente rápida em recuperar os bytes (seek) é a TGpHugeFileStream. Esta

FileReader – lendo bytes e frases sem carregar todo o arquivo

classe open-source tem boa capacidade de resposta para arquivos grandes, pois foi designada especialmente para este fim – então podemos ler sempre um intervalo entre os bytes de origem e destino – sem estourar a memória. Claro que não vamos definir um intervalo do tamanho deste arquivo a ser pesquisado, já que isso equivale a abrir um arquivo inteiro. A questão é definir um filtro e extrair ele.

Definindoumintervalodepesquisa

Este método implica alguns passos para seu correto funcionamento – criar o componente, instanciar, atribuir à propriedade position o offset de origem até o byte de destino – segue uma ordem lógica abaixo:

1. Criar e instanciar a classe TGpHugeFileStream;2. Definir a posição (position) através de seu offset (byte origem da

pesquisa);3. Preencher um buffer – (array do tipo AnsiChar) com a quantidade

de bytes a serem obtidos nesta pesquisa definida no passo 2;4. Ler este buffer, filtrando caracter a caracter – pois os caracteres

não imprimíveis não serão filtrados;5. Alimentar uma string com este buffer, para pesquisar todos os

caracteres de quebra de linha (Carriage Return/ Line Feed) – e com a quanti-dade de linhas a serem pesquisadas buscar todas as ocorrências deste caracter pesquisado para retornar as linhas desejadas.

Segue abaixo o trecho básico de código-fonte responsável por esta im-plementação:

procedure TForm1.btnProcessReadClick(Sender: TObject);var

Page 9: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 09

File64: TGpHugeFileStream; Buffer: array of AnsiChar; TempStr: string; sw : TStopWatch; i: integer; line: integer; totalLines: Int64; NewBuffer: string; Readed: Int64; FBuffer: string; iSeekPosition: integer; fMode: Word;begin { TStream seek origins from Classes.pas VCL ... { soFromBeginning = 0; soFromCurrent = 1; soFromEnd = 2; }File64 := TGpHugeFileStream.Create(edtFileName.Text, accRead); sw := TStopWatch.Create; try CheckListBox1.Clear;

CheckListBox1.Items.BeginUpdate; try sw.Start;

iSeekPosition := cbSeekPosition.ItemIndex; case iSeekPosition of 0: begin fMode := soFromBeginning; File64.Position := File64.Seek(StrToInt64Def(edtOffset.Text, 1), fMode); end; 1: begin fMode := soFromCurrent; File64.Position := File64.Seek(StrToInt64Def(edtOffset.Text, 1), fMode);

end; 2: begin fMode := soFromEnd; File64.Position := File64.Seek(1-StrToInt64Def(edtOffset.Text, 1), fMode); end; end;

SetLength(Buffer, StrToIntDef(edtBytesLimit.Text,100)); File64.Read(Buffer[0],StrToIntDef(edtBytesLimit.Text,100)); Readed := 1;

for i := Low(Buffer) to High(Buffer) do if (Buffer[i] in cAllowed) then FBuffer := FBuffer + Buffer[i];

//FBuffer := pansichar(buffer); totalLines := StrToIntDef(edtMaxLines.Text,1); Dec(totalLines); for line := 0 to totalLines do begin while (Pos(#13, FBuffer) = 0) and (Readed > 0) do begin SetLength(NewBuffer, BufferLength + 2); Readed := File64.Read(NewBuffer[1], BufferLength); SetLength(NewBuffer, Readed); FBuffer := FBuffer + NewBuffer; end; if Pos(#13, FBuffer) >

Page 10: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201510

0 then begin TempStr := Copy(FBuffer, 1, Pos(#13, FBuffer) - 1); Delete(FBuffer, 1, Pos(#13, FBuffer) + 1); end else begin TempStr := FBuffer; FBuffer := ‘’; end;

if (TempStr <> ‘’) then CheckListBox1.Items.Add(TempStr); Application.ProcessMessages; end; finally CheckListBox1.Items.EndUpdate; end;

sw.Stop; stStopWatch.Caption := ‘Elapsed ‘ + Self.FormatMillisecondsToDateTime(sw.ElapsedMilliseconds); finally FreeAndNil(File64); FreeAndNil(sw); end; end;

Figura 01 – Implementação da função de leitura parametrizada pelo número de linhas a serem lidas, cujos bytes pesquisados de origem (offset) e destino também foram parametrizados.

Figuras 02/03 – Implementação principal da leitura por intervalo de bytes.Contando o total de linhas em arquivos grandes

Segue abaixo uma implementação segura e confiável de como contar todas as linhas de arquivos grandes, sem travar a aplicação nem ocasionar erros de memória. Novamente a classe TGpHugeFileStream é utilizada. Foi testado principalmente em arquivos maiores que 1 GB (abaixo segue uma figura de um teste com um arquivo de 2 GB) em que aproximadamente 25 milhões de linhas foram contadas em um tempo estimado de 30 segundos.

Esta função permite a contagem em qualquer arquivo do tipo texto – o que deve ser levado em consideração é o tempo de resposta que é proporcional ao tamanho do arquivo a ser contado. Portanto, quanto maior seu tamanho, mais tempo será levado para ser contado suas linhas. Ressaltando que funciona apenas para arquivos do modo texto. Não deve funcionar corretamente em arquivos do modo binário.

function TForm1.GetLineCount(const FileName: string): Integer;var FS: TGpHugeFileStream; //TFileStream Buff: array[0..1023 * SizeOf(Char)] of Char; Temp: string; i: Integer; sz: Int64;begin Result := 0; FS := TGpHugeFileStream.Create(FileName, accRead); //TFileStream.Create(FileName, fmOpenRead); try sz := fs.Size; while FS.Position < sz do begin

Page 11: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 11

FS.Read(Buff[0], Length(Buff)); Temp := Buff; i := PosEx(#13#10, Temp); while i > 0 do begin Inc(Result); i := PosEx(#13, Temp, i + 2); Application.ProcessMessages; end; end; finally FS.Free; end;end;

{ ... } sw.Start; Memo1.Lines.Add(Format(cTotalLoadedLines, [FormatFloat(‘#,’,Self.GetLineCount(edtFileName.Text))])); finally sw.Stop; Memo1.Lines.Add(‘Elapsed ‘ + Self.FormatMillisecondsToDateTime(sw.ElapsedMilliseconds)); FreeAndNil(sw); end;

Figuras 04 – Implementação da função de contagem de linhas para arquivos grandes (no teste acima, arquivo de 2GB).

Duas coisas importantes e interessantes devem ser levadas em considera-ção para agilizar a função de contagem de linhas, trazendo maior performance e eficiência nesta implementação:

1. Armazenar a propriedade size para uma variável local. Fazendo isso as chamadas serão muito mais rápidas – isso porque esta propriedade, que é virtual, chama a função kernel32.FileSeek três vezes (a API do Windows é lenta para este nosso propósito) – utilizando em um cache local a chamada será apenas uma;

2. Utilizar os métodos read() e write() ao invés de readBuffer() e wri-teBuffer(), respectivamente. Isso porque eles já chamam internamente estes métodos, aumentando o overhead desnecessário de consultas.

Com isso, vimos as melhores formas de se pesquisar por linhas qualquer arquivo texto de qualquer tamanho. O código-fonte exibido acima (GetLine-Count) está bem otimizado e felizmente trará boa performance nos resultados de contagem de linha. Esta função sempre poderá ser vista como base para outras implementações, como por exemplo:

1. Procurar por texto linha a linha;2. Procurar por algumas linhas selecionadas;3. Obter os textos das frases de cada linha retornada;4. Alterar os dados de alguma frase da linha desejada;5. Pesquisar em um diretório todos os arquivos contidos nele e todas

as suas linhas, até que um método de pesquisa seja alcançado (por exemplo, via mecanismo de consulta padrão regex).

Pesquisando linhas e retornando suas frases – array e delimitadores

Para ilustrar algumas das ideias citadas acima, vamos construir um protó-tipo destas citações para ilustrar de uma maneira mais profissional como nossa aplicação de contagem de linhas pode pesquisar por parâmetros das linhas e retornar as suas frases relacionadas. E isso é uma boa ideia de como podemos abrir uma parte de um arquivo (não vamos carregar ele inteiro, a não ser que a linha a ser pesquisada realmente esteja no final dele) e recuperar as frases relacionadas nessas linhas.

O nosso algoritmo básico se resume a estes passos:

1. O usuário informa o arquivo a ser aberto;2. O usuário define as linhas a serem pesquisadas, possibilitando

elas a serem parametrizadas por delimitadores pré-definidos na constante cDelimiters ( [‘.’, ‘,’, ‘:’, ‘;’, ‘-’, ‘!’, ‘?’];

3. O usuário solicita a pesquisa clicando o botão para realizar este procedimento;

4. O sistema devolve os resultados das linhas que foram encontradas. Se a linha do arquivo for superior ao valor mais alto do array pesquisado a pesquisa será encerrada, pois não haverá mais a necessidade de realizar a pesquisa visto que todas as linhas de pesquisa contidas no array já foram encontradas e retornadas.

Com alguns esforços, termino a implementação da pesquisa por linhas parametrizada por delimitadores. Claro que algumas coisas poderiam ser melhoradas, mas fica para uma próxima versão, como por exemplo a defi-nição do intervalo de forma sequencial mapeada para o delimitador “hífen” (-) – exemplo: 2-8 => resulta => pesquisar da linha 2 ATÉ a linha 8. Essa característica não é suportável para esta versão, no momento. Mas fácil de aperfeiçoar posteriormente.

Page 12: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201512

Importante ressaltar a utilização de outras classes intermediárias, como um TMemoryStream e um TStringList para obter a leitura do arquivo parte por parte e quebrar as partes em linhas, respectivamente.

Por enquanto todos os delimitadores resultam no mesmo comportamen-to; são linhas sem intervalos, apenas elas - ‘.’, ‘,’, ‘:’, ‘;’, ‘-’, ‘!’, ‘?’ – utilizadas ao mesmo tempo ou apenas uma ou um conjunto delas – sempre extrairão as linhas sem intervalo – exemplo 2;5-7 => resulta => pesquisar as linhas 2,5 e 7. Mas não entre elas (intervalo). Como disse, não nesta versão inicial ainda.

Basicamente é isso. A aplicação agora está pronta para varrer o arquivo, quebrando em linhas, linha por linha, verificando se a linha pesquisada é a desejada para exibição, e por fim exibindo elas uma a uma em um objeto do tipo TMemo. E como já vimos o objeto do tipo TStringList foi utilizado para auxiliar na contagem delas. Problema resolvido.

Segue abaixo o código-fonte responsável por essa nossa implementação de contagem de linhas específicas por parametrização por delimitadores.

procedure TfrmMain.LoadTextBySelectedLines(const FileName: string);var File64: TGpHugeFileStream; PartFileSize: integer; i, k: integer; sw : TStopWatch; StrmOutput: TMemoryStream; strList: TStringList; TotalPartsToDivide: Integer; OriginalFileSize: Int64; sz: Int64; auxStr: string;begin Memo1.Lines.Clear; //Memo1.Lines.BeginUpdate; sw := TStopWatch.Create; lineCounter := 0;

try OriginalFileSize := Self.GetFileSize(FileName); PartFileSize := NumberOfPartsToDivide(OriginalFileSize); TotalPartsToDivide := System.Round(OriginalFileSize/PartFileSize); except on E:Exception do Raise Exception.Create(E.

Message); end;

if (Self.RoundUpWithDecimais(OriginalFileSize/PartFileSize, 2)) > (TotalPartsToDivide) then Inc(TotalPartsToDivide);

ProgressBar.Max := TotalPartsToDivide; ProgressBar.Position := 0;

File64 := TGpHugeFileStream.Create(FileName, accRead); try sw.Start; PartFileSize := Self.NumberOfPartsToDivide(Self.GetFileSize(FileName)); File64.Position := 0; sz := File64.Size; strList := TStringList.Create;

auxStr := edtLines.Text; arLines := split(auxStr, cDelimiters);

while (File64.Position < sz) do begin if (sz - File64.Position < PartFileSize) then PartFileSize := (sz - File64.Position);

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

for i := 0 to strList.Count - 1 do begin for k := low(arLines) to high(arLines) do begin if (lineCounter = arLines[k]) then

Page 13: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 13

Memo1.Lines.Add(Format(cLineAndTextFound, [FormatFloat(‘#,’,lineCounter), strList.Strings[i]])); end; if (lineCounter = MaxIntValue(arLines)) then begin ProgressBar.Position := ProgressBar.Max; Memo1.Lines.Add(Format(cSuccessfullyFinished, [FormatFloat(‘#,’,lineCounter)])); Exit; end;

Inc(lineCounter); end; ProgressBar.Position := ProgressBar.Position + 1; Application.ProcessMessages; finally FreeAndNil(StrmOutput); end; end; finally sw.Stop; Memo1.Lines.Add(‘Elapsed ‘ + Self.FormatMillisecondsToDateTime(sw.ElapsedMilliseconds)); FreeAndNil(File64); FreeAndNil(strList); FreeAndNil(sw); //Memo1.Lines.EndUpdate; end; Memo1.Lines.Add(Format(cTotalLoadedLines, [FormatFloat(‘#,’,lineCounter)]));end;

{ ... }

function TfrmMain.split(const str: string; const delims: TCharSet): IntegerArray;var SepPos: IntegerArray; i: Integer;

begin SetLength(SepPos, 1); SepPos[0] := 0; for i := 1 to length(str) do if str[i] in delims then begin SetLength(SepPos, length(SepPos) + 1); SepPos[high(SepPos)] := i; end; SetLength(SepPos, length(SepPos) + 1); SepPos[high(SepPos)] := length(str) + 1; SetLength(result, high(SepPos)); for i := 0 to high(SepPos) - 1 do result[i] := StrToIntDef( Trim(Copy(str, SepPos[i] + 1, SepPos[i+1] - SepPos[i] - 1)),0);end;

function TfrmMain.NumberOfPartsToDivide(const filesize: integer): integer;var denominator: integer; { Em fração, o denominador corresponderá a quantidade de partes exatas em que será dividido o arquivo, enquanto que o numerador será o tamanho do arquivo. }begin case length(IntToStr(Round(filesize))) of //convert to bytes 1: denominator := 4; 2: denominator := 8; else denominator := Round(Math.Power(10, length(IntToStr(filesize)) - Round(length(IntToStr(filesize)) / 2))); end; Result := Round(filesize/denominator) * 100;end;

Page 14: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201514

Conclusão

Vimos três implementações diferentes de contagem de linhas de arquivos – a de contagem simples (que apenas conta todas as linhas e pronto) – a de contagem por pesquisa de linhas (separado por delimitadores) e por offset – intervalo de bytes. Trouxemos estas três idéias de como obter as linhas desejadas por parâmetro, ou seja, pesquisa por linhas, até que a última seja encontrada e com isso o programa é encerrado – não é necessário percorrer todo o arquivo a não ser que a linha a ser procurada seja a última do arquivo – aí nesse caso equivale mesmo contar todo o arquivo de uma só vez. Mas mesmo assim a performance é significativa em todos os casos.

Uma coisa a ser observada é como a classe TGpHugeFileStream é uma “mão na roda” – agilizando nos nossos testes e contando as linhas – podemos sempre ter a necessidade “rápida” de verificar algum dado em alguma linha ou em algum conjunto delas – sem ter que carregar todo o arquivo de uma vez – arquivos grandes são sempre um problema na hora de exibir o conteúdo nos controles visuais da VCL. Alternativas como a listview ou listbox virtual também nem sempre serão tão rápidas assim – se comparado a exibição “par-cial” de algumas linhas apresentadas neste artigo podemos perceber que é a alternativa mais rápida – embora o projeto “FastFile” apresentado na edição anterior também seja interessante em carregar todo o arquivo de uma vez – então temos aqui a questão de praticidade e de tempo para o usuário – ambos os projetos tem seus prós e contras – mas apresentam o resultado de forma satisfatória e eficiente, sem onerar o sistema operacional.

Portanto, os projetos mostrados aqui podem ser estendidos para melhores funcionalidades no sentido de contagem de linhas e suas manipulações – como por exemplo, alteração nas linhas desejadas (método write), melhoria nas pa-rametrizações dos delimitadores de pesquisa, exportação das linhas para um novo arquivo, ou finalmente, alteração de todas as linhas ou parte delas para um formato texto de tamanho fixo – como um arquivo de carga – porque não?

Assim, desejamos uma boa leitura a todos e até a próxima. Bons estudos e aproveitem!

[email protected]

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

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

Sobre o autor

Page 15: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 15

Todo desenvolvedor já se deparou em uma situação que precisou fazer o uso de “Threads”. Antes de partirmos para a parte prática gostaria de discorrer um pouco delas.

Explicandoumpouquinho

As denominadas “Threads” significam “linhas de execuções”, seria uma forma de um processo dividir a si mesmo em duas ou mais tarefas que podem ser executadas concorrentemente. (Fonte: https://pt.wikipedia.org/)

Um bom exemplo disto seria o próprio Sistema Operacional, o mesmo trabalha com as denominadas Multi-threads, onde se divide as linhas de execução aumentando sua eficiência. Poderemos imaginar uma “Thread” como um trecho de código que é executado em paralelo ao seu código, sen-do que podem existir diversas threads executando em um dado momento. A partir do momento que você cria uma thread, o Sistema Operacional fica sabendo que, além de tudo que já está fazendo, há mais código que precisa ser executado. Se existem mais threads do que processadores/núcleos (que é o caso mais visto nos computadores pessoais e dispositivos móveis), então o Sistema Operacional começa a “agendar um momento” para que cada thread execute em um determinado núcleo/processador (processo conhecido como escalonamento, ou agendamento).

ComoFuncionanoC#?

É importante lembrar que todo programa desenvolvido em C# possui uma thread, denominada “Thread Principal”. Quando montamos rotinas que demandam um tempo maior e se a thread principal for dedicada a isto, o programa pode parar de responder até que sua execução seja concluída. (Por exemplo, uma rotina que utiliza um laço para ler 1.000.000 de registros e a partir dele alimentar uma Barra de Progresso). Neste caso para permitir que este mesmo programa execute esta tarefa e continue a responder normalmente deveremos implementar o uso de “Threads”. Realizando o processamento

em segundo plano melhoramos o desempenho das tarefas do processador consequentemente reduzindo o tempo que leva para completar esta tarefa.

ConhecendoaClasse“Thread”

Neste tópico irei explicar algumas das principais funcionalidades da classe Thread. Importante lembrar que todas estas informações foram baseadas na versão 4.5 e 4.5 do .Net Framework. A classe Thread respeita a hierarquia abaixo:

Sytem.Object System.Runtime.ConstrainedExecution.CriticalFinalizerObject System.Threading.Thread

Possuindo outras classes bases para sua implementação.

Sintaxe

A sintaxe poderá ser conferida no código abaixo:

ComVisibleAttribute(true)]ClassInterfaceAttribute(ClassInterfaceType.None)]public sealed class Thread :

Linguagem C# - TrabalhandocomThreadsemWindowsForms

Page 16: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201516

CriticalFinalizerObject, _Thread

Principaiscomandos(Construtores,PropriedadeseMétodos)

Antes de partirmos para a parte prática, achei de extrema importância apontar os principais comandos quando fazemos o uso de “Threads”. Come-çando pelo Construtor seguindo pelas suas propriedades e finalizando com seus Métodos.

ConhecendoosConstrutores

1)Thread(ParameterizedThreadStart)Teremos como inicialização uma nova instância da classe Thread, espe-

cificando um delegate (o mesmo permite que um objeto seja passado para o segmento quando este for iniciado.)

2)Thread(ParameterizedThreadStart,Int32)Possui as mesmas características citadas acima, adicionando como segundo

parâmetro o tamanho máximo de pilha para o segmento.

3)Thread(ThreadStart)Apenas inicia uma nova instância para a classe.

4)Thread(ThreadStart,Int32)Inicia uma nova instância especificando o tamanho máximo de pilha para

o segmento.

ConhecendoasPropriedades

1)CurrentContextEsta propriedade obtém o contexto atual em que o segmento está sendo

executado.

2) CurrentCultureTem como objetivo obter ou definir a contura para o segmento atual.

3) CurrentPrincipalObtém ou define o principal atual da thread (para segurança baseada

em função).

4)CurrentThreadEsta propriedade nos informa o thread em execução no momento.

5)ExecutionContextRetorna um objeto que contém todas informações sobre os diferentes

contextos de segmentos que estão sendo executados no momento.

6) IsAliveValor do status de execução atual.

7)IsBackgroundPropriedade que indica se o segmento é um segmento de plano de fundo.

8)IsThreadPoolThreadObtém um valor indicando se um segmento pertence ao thread pool

gerenciado.9)ManagedThreadIdObtém um identificador exclusivo para o segmento gerenciado atual.

10)NameDefinição ou obtenção de um nome do segmento.

11)PriorityObtém ou define um valor que indica a prioridade de programação de

um segmento.

12)ThreadStateObtém um valor que contém os estados de segmento atual.

ConhecendoosMétodos

1)Abort()Método para encerrar a Thread.

2) AllocateDataSlotEste método atribui um slot sem nome de dados em todos os segmentos.

Para melhor desempenho, campos de uso marcados com o atributo de Thre-adStaticAttribute em vez disso.

3)BeginThreadAffinitytem como objetivo notificar um host que o código gerenciado está prestes

a executar instruções que dependem da identidade do segmento físico atual do Sistema Operacional.

4)EndThreadAffinityTem a finalidade de notificar um host que o código gerenciado terminou

de executar instruções que dependem da identidade do segmento físico atual do sistema operacional.

5) GetDataEste método recupera o valor do slot especificado no segmento atual,

dentro do domínio atual da thread atual. Para melhor desempenho, campos de uso marcados com o atributo de “ThreadStaticAttribute” em vez disso.

6) Join()Bloquear o segmento de chamada até que um segmento termina, para

continuar a executar com padrão e o bombeamento de “SendMessage”.

7)ResetAbort()Abortar o aplicativo para o segmento atual.

8) SetDataDefinir os dados no slot especificado no thread em execução no momento,

Page 17: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 17

para o domínio atual do segmento. Para melhor desempenho, use os campos marcados com o atributo de “ThreadStaticAttribute” em vez disso.

9) Sleep(int32)Suspende o segmento atual por um período especificado.

10) Start()Faz com que o sistema operacional modifique o estado da instância atual

a “ThreadState.Running”.

1)Criandoumexemplopráticoviaconsole

No primeiro momento iremos demonstrar como devemos proceder para criar uma Thread via console. Para isto clique “File/New/Project...” escolhendo “Console Application”. Ver Imagem 01.

Figura 01: Thread via console.

Este projeto irá possuir apenas uma classe principal chamada “Threa-dExemploConsole”, a que será executada quando compilarmos e rodarmos o programa. No próprio exemplo abaixo irei descrevendo todos os passos. Primeiramente deveremos importar algumas bibliotecas para esta tarefa. Ver Listagem 01.

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Threading;

namespace ConsoleApplicationThreads{ public class

ThreadExemploConsole {

public static void ThreadProc() { for (int i = 0; i < 10; i++) { Console.WriteLine(“ThreadProc: {0}”, i); Thread.Sleep(10); } }

Dentro da classe pública e estática iremos criar um método estático cha-mado “ThreadProc()”, produziremos a Thread secundária a partir dele. Faremos um Loop e escreveremos na tela a cada iteração realizada.

public static void Main() {Console.WriteLine(“Thread principal: Iniciando a segunda Thread.”);

Thread t = new Thread(new ThreadStart(ThreadProc)); t.Start(); Thread.Sleep(20); for (int i = 0; i < 4; i++) {Console.WriteLine(“Thread Principal: Executando...”); Thread.Sleep(0); }

Console.WriteLine(“Thread principal : Método Join() esperando até a segunda Thread terminar.”); t.Join();

Page 18: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201518

Console.WriteLine(“Thread principal : Segunda Thread finalizou. Pressione Enter para finalizar programa.”); Console.ReadLine(); }

A partir do construtor da classe Thread, passaremos como parâmetro a thread secundária seguido do método “ThreadStart” (para iniciá-la). Lembran-do que este parâmetro é um “delegate”, necessário para utilizar o método “ThreadProc”. Logo após usaremos os métodos: Start() e Sleep(), respecti-vamente para iniciar a tread principal fazendo com que a thread secundária aguarde o término da mesma. Teremos uma noção clara do funcionamento analisando o resultado obtido através da Imagem 02.

}}

Listagem 01.

Figura 02: Resultado - Saída de Dados.

2)CriandoumexemplopráticoviaWindowsForms

A ideia deste exemplo seria de demonstrar de uma forma simples o uso de “Threads” em tarefas que podemos nos deparar no dia-a-dia. Quem nunca precisou criar uma rotina para leitura de dados de uma tabela por exemplo? Geralmente quando precisamos realizar iterações com uma grande quantidade de elementos é imprescindível possuir uma interface amigável para o usuário, na maioria das vezes podemos implementar o uso de uma barra de progresso junto com as “Threads”, permitindo executar mais de um processo por vez, como foi explicado no exemplo anterior. Com aplicações Windows Forms precisaremos implementar o uso de Delegates, para assim podermos executar as Threads Secundárias. Para isto adicione no formulário um “Button” e um “ProgressBar”. Ver Figura 03.

Figura 03: Trabalhando com Threads em Windows Forms.

Abaixo a codificação necessária, Ver Listagem 02

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Text.RegularExpressions;using System.Threading;using System.Reflection;

Primeiramente importaremos algumas bibliotecas necessárias.

namespace WindowsFormsApplicationThreads{ public partial class FrmThreads : Form { public FrmThreads() { InitializeComponent(); }

private void btnIniciar_Click(object sender, EventArgs e)

Page 19: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 19

{Thread thread = new Thread(new ThreadStart(ExecutarLoop)); thread.IsBackground = true; thread.Start(); }

No botão “Iniciar” é onde faremos a chamada da “Thread”. Primeiramente passaremos como parâmetro o método “ExecutarLoop” invocando o método “ThreadStart”. A propriedade “IsBackground” especifica a thread como plano de fundo. O método “Start()” irá inicializá-la.

. public void ExecutarLoop() { int total = 100000; int incrementaValor = 0;

SetControlPropertyValue(progressBar1, “value”, 1);SetControlPropertyValue(progressBar1, “minimum”, 1);SetControlPropertyValue(progressBar1, “maximum”, total);

/* Implementando Threads */ while (incrementaValor < total) {incrementaValor = progressBar1.Value + 1;SetControlPropertyValue(progressBar1, “value”, incrementaValor); } }

Este método fará um laço para preencher uma barra de progresso. Não

podemos esquecer que trabalhar com threads junto com windows forms de-veremos fazer o uso de um “delegate” (Para maiores informações sobre este asssunto recomendo a leitura do artigo do mês de Maio de 2015 chamado “Linguagem C# - Delegates em Windows Forms”)

A solução abaixo foi encontrada através do seguinte site: http://shabdar.org/c-sharp.html e comentada também em http://www.macoratti.net

delegate void SetControlValueCallback(Control oControl, string propName, object propValue);

Iremos declarar um delegate responsável por atualizar valores da Thread Secundária.

private void SetControlPropertyValue(Control oControl, string propName, object propValue) { if (oControl.InvokeRequired) {SetControlValueCallback d = new SetControlValueCallback(SetControlPropertyValue);oControl.Invoke(d, new object[] { oControl, propName, propValue }); } else { Type t = oControl.GetType(); PropertyInfo[] props = t.GetProperties(); foreach (PropertyInfo p in props) {if (p.Name.ToUpper() == propName.ToUpper()) {

Page 20: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201520

p.SetValue(oControl, propValue, null); } } } } }}

Listagem 02.

Este método “SetControlPropertyValue” terá como parâmetro de entrada o tipo de controle, a propriedade e o valor.

Podemos conferir o resultado na Figura 04. Veja a Figura 04: Exemplo em Execução.

Conclusões

O uso de “Threads” se torna uma prática muito utilizada no desenvol-vimento de programas. Determinadas tarefas que encontramos o uso deste mecanismo se torna indispensável para aumentar a qualidade do código e do resultado final para o usuário.

Com este artigo procurei demonstrar os principais construtores, métodos e

propriedades da classe “Thread” junto com exemplos simples que os ajudarão a adaptar para praticamente todas as necessidades.

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

Referências

https://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspxhttps://msdn.microsoft.com/pt-br/l ibrary/system.threading.

thread%28v=vs.110%29.aspx

Figura 04: Exemplo em Execução.

[email protected]

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

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

Sobre o autor

Page 21: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 21

Listagem 1. Classe para manipular os dados dos amigos

No artigo anterior, fizemos um exemplo de como logar com o Facebook em uma aplicação Android, usando o FaceBook SDK. Neste artigo quero mostrar como interagir mais com essa rede social, retornando a listagem de amigos.

Listagemdeamigos

Vamos criar uma listagem que exibirá todos os amigos. A ideia é poder divulgar da sua app. Primeiramente, vamos modificar o código do primeiro artigo, onde validamos se o usuário já esta logado no facebook. O código usava o getActiveSession, mas ainda precisamos fazer outra validação, caso o mesmo retorne null. Veja como ficará o código:

Session sessao = Session.getActiveSession();

if (sessao == null) sessao = Session.openActiveSessionFromCache(this);

if (sessao == null){ Intent login = new Intent(MainActivity.this, LoginActivity.class); startActivity(login);}

API2.0

O Facebook fez algumas modificações em sua API, isso impactou bastante em apps que retornavam a listagem de amigos. Atualmente, a lista de amigos sempre retorna null (vazia). Fiz várias pesquisas, e todas me diziam que o pro-blema era de permissão. Visualizando as permissões que a app tem, indicava que a listagem de amigos tinha permissão.

Achei uma resposta para essa questão bem explicada nesse link: http://stackoverflow.com/questions/23417356/facebook-graph-api-v2-0-me-friends-

-returns-empty-or-only-friends-who-also-u.

Nesse link, também temos uma alternativa para conseguir o retorno dos amigos e baseado nela que vamos implementar a nossa funcionalidade de retornar os amigos. Primeiramente, vamos criar uma Activity que será a responsável por exibir os amigos em uma ListView.

Clique no pacote da app (br.com.theclubandroid) e escolha a opção New>Activity>Blanck Activity. No wizard, temos a facilidade de escolher o nome da Activity, juntamente com o layout vinculado ao mesmo, além de definir menu, pacote etc (Figura 1).

Figura 1. Criando uma nova Activity

Adicione um ListView no arquivo de layout. Crie uma nova classe chamada “FacebookFriend” e implemente, conforme a Listagem 1.

String id;String nome;

IntegraçãoAndroideFacebook– Parte II

Page 22: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201522

Listagem 2. Criando a classe que retornara os amigos

String imagemURL;boolean invitable;private boolean isValid;

public boolean isValid() { return isValid;}

public void setIsValid(boolean isValid) { this.isValid = isValid;}

public FacebookFriend(JSONObject jsonObject) { try { this.id = jsonObject.getString(“id”); this.nome = jsonObject.getString(“name”);

JSONObject pictureJsonObject = jsonObject.getJSONObject(“picture”).getJSONObject(“data”); boolean isSilhouette = pictureJsonObject.getBoolean(“is_silhouette”); if (!isSilhouette) { this.imagemURL = pictureJsonObject.getString(“url”); } else { this.imagemURL = “”; }

this.invitable = true;

setIsValid(true); } catch (JSONException e) {

}}

A classe, recebe um JSONObject e manipula o mesmo configurando suas propriedades com os valores retornados pelo Facebook. Essa classe só tem esse objetivo. Vamos agora, criar a classe que vai pesquisar os amigos e repassar para o FacebookFriend o JSONObject.

ConsultacomJSON

Acesse FriendsActivity e adicione o código da Listagem 2.

private class DownloadFacebookFriendsTask extends AsyncTask<String, Boolean, Boolean> { private final String TAG = DownloadFacebookFriendsTask.class.getSimpleName(); GraphObject graphObject; ArrayList<FacebookFriend> myList = new ArrayList<FacebookFriend>(); private ProgressDialog pDialog;

@Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(FriendsActivity.this); pDialog.setMessage(“Carregando amigos...”); pDialog.setIndeterminate(false); pDialog.setCancelable(true); pDialog.show(); }

@Override protected Boolean doInBackground(String... param) {

new Request( Session.getActiveSession(), “/me/taggable_friends”, null, HttpMethod.GET, new Request.Callback() { public void onCompleted(Response response) { graphObject = response.getGraphObject(); }

Page 23: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 23

Listagem 3. Preenchendo o ListView

}).executeAndWait();

if (graphObject == null) { return false; }

int numberOfRecords = 0; JSONArray dataArray = (JSONArray) graphObject.getProperty(“data”);

if (dataArray.length() > 0) {

for (int i = 0; i < dataArray.length(); i++) {

JSONObject jsonObject = dataArray.optJSONObject(i); FacebookFriend facebookFriend = new FacebookFriend(jsonObject);

if (facebookFriend.isValid()) { numberOfRecords++;

myList.add(facebookFriend); } } }

if (numberOfRecords > 0){ return true; } else { return false; } }

@Override protected void onPostExecute(Boolean result) { if (result) {

//preenche o ListView pDialog.dismiss();

} }}

Usamos o AsyncTask para ter outra thread e também um ProgressDia-log. No doBackground é onde fizemos a requisição para os amigos (me/taggable_friends). No onComplete, repassamos para o objeto GraphObject o retorno do response.

Repassamos para uma variável o JSONArray e chamamos, dentro de um laço, a classe FacebookFriend, criada anteriormente. Após a validação, adi-cionamos em uma lista, o item do laço, para posteriormente, vincular a lista com o ListView. Por fim, no onPostExecute, fechamos nossa ProgressDialog e também nesse método que preencheremos a ListView.

Para visualizarmos a app funcionando, vamos preencher com um array de string o ListView. Adicione no onPostExecute, o código da Listagem 3.

String[] listaAmigos = new String[myList.size()];

for (int i =0; i < myList.size(); i++){ listaAmigos[i] = myList.get(i).nome;}

ListView list = (ListView)findViewById(R.id.listView);ArrayAdapter<String> adapter = new ArrayAdapter<String>(FriendsActivity.this, android.R.layout.simple_list_item_1, listaAmigos);list.setAdapter(adapter);

Adicione o código a seguir, no onCreate do FriendActivity:

new DownloadFacebookFriendsTask().execute();

Por fim, adicione um botão na tela principal e chame a tela de amigos (FriendActivity). Rode a aplicação e veja a listagem de amigos (Figura 2).

Veja a Figura 2. Retorno da listagem de amigos do Facebook

Temos nessa listagem, apenas o nome, mas podemos incrementar, adi-cionando a foto.

CustomizandooListView

Quem acompanhou a série sobre Android Studio, lembra que podemos

Page 24: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201524

Listagem 4. Controles de tela para o item do ListView

Listagem 4. Método para fazer download da imagem

customizar o Adapter que preenche um ListView. Vamos criar um, para “mon-tar” a listagem como queremos (com imagem). Primeiramente, vamos criar o layout do item do ListView. Crie outro arquivo de layout (apenas layout, sem Activity) e dê o nome de “itens_friends.xml” e o tipo será RelativeLayout .

Adicione os controles, conforme a Listagem 4.

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

<TextView android:id=”@+id/nomeFriend “ android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:textColor=”#040404” android:text=”Nome do amigo” android:typeface=”sans” android:textSize=”15dip” android:paddingLeft=”7dp”

android:layout_centerVertical=”true” android:layout_toRightOf=”@+id/thumbnail” android:layout_toEndOf=”@+id/thumbnail” />

Adicionamos um ImageView e um TextView. A disposição dos controles nos dará um layout como o da Figura 3.

Figura 3. Layout para a “linha” do ListView

Precisamos modificar a classe que manipula os dados dos amigos, para pegar a imagem do mesmo. O Facebook libera uma URL com a imagem, portanto, vamos fazer o download em memória da imagem. A desvantagem do download é a quantidade de amigos que você pode ter, assim, o processo pode/deve ser demorado.

Vamos modificar a classe FacebookFriend, para que a mesma armazene em uma propriedade (Bitmap) a imagem do amigo. Crie primeiramente, a propriedade:

Bitmap imagem;

Agora, vamos implementar o método que fará o download da imagem e armazenara na propriedade criada, como vemos na Listagem 4.

private Bitmap downloadFile(String param) throws IOException {

Bitmap bmp = null;URL url = new URL(param);InputStream in = new BufferedInputStream(url.openStream());

try {

Figura 2. Retorno da listagem de amigos do Facebook

Page 25: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 25

Listagem 5. Criando o adapter

bmp = BitmapFactory.decodeStream(in);

} catch (Exception e) {

e.printStackTrace();

} finally { try { in.close(); } catch (Exception e2) { }}

return bmp;}

No código temos como parâmetro, o caminho (URL) da imagem. O do-wnload é feito com um InputStream e convertemos para Bitmap, usando o decodeStream, que é o retorno da função. Agora no Create da classe, temos que modificar o código para preencher a propriedade:

...this.imagemURL = pictureJsonObject.getString(“url”);

try{ imagem = this.downloadFile(this.imagemURL);}catch (Exception e){}...

Criando o adapter

Agora, precisamos criar um adapter. Crie uma nova classe e dê o nome de “FacebookAdapter”. Adicione o código da Listagem 5.

public class FacebookAdapter extends BaseAdapter { private static LayoutInflater inflater = null; private Activity activity; private ArrayList<FacebookFriend> data;

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

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

public Object getItem(int position) { return position; }

public long getItemId(int position) { FacebookFriend friend = data.get(position); return Long.parseLong(friend.id); }

public View getView(int position, View convertView, ViewGroup parent) { View vi = convertView;

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

ImageView imagem = (ImageView) vi.findViewById(R.id.thumbnail); TextView name = (TextView) vi.findViewById(R.id.nomeFriend);

FacebookFriend friend = data.get(position);

name.setText(friend.nome); imagem.setImageBitmap(friend.imagem);

return vi; }}

Page 26: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201526

Listagem 6. Modificando para paginar o ListView

Recebemos como parâmetro uma lista de amigos, classe responsável por manipular os dados dos amigos. No getView é onde vamos trabalhar os dados com os controles de tela adicionados no arquivo de layout.

Primeiro, temos que carregar o arquivo de layout (inflater) para depois, instanciar os controles, configurando as respectivas propriedades. Por fim, na tela de listagem de amigos, vamos alterar o código que preenchemos o ListView com o seguinte código:

ListView list = (ListView)findViewById(R.id.listView);list.setAdapter(new FacebookAdapter(FriendsActivity.this, myList));

Veja na Figura 5 a apresentação da lista de amigos e suas fotos.

Figura 5. Listagem de amigos com fotos de perfil

Dependendo da quantidade de registros retornados, a app ficará lenta. No meu exemplo, temos mais de 200 amigos, assim, demorou alguns minutos para download de todas as imagens. Isso que temos que levar em conta o hardware do seu device, e claro a sua conexão de dados.

Uma ideia para melhorar isso, seria paginar o ListView, para que retorne, apenas a quantidade de registros que queremos.

PaginandooListView

Vamos implementar a funcionalidade de retornar apenas uma quan-tidade de amigos, assim que o usuário chegar ao final, teremos que fazer outra pesquisa e retornar o restante que definirmos. Precisamos modificar o código do DownloadFacebookFriendsTask. Primeiramente, vamos alterar as propriedades myList e dataArray para que fiquem como propriedades da classe FriendsActivity:

ArrayList<FacebookFriend> myList = new ArrayList<FacebookFriend>();JSONArray dataArray = null;

A ideia é que vamos carregar a dataArray e depois, manipular essa lista para que retorne somente a quantidade de registros que precisamos. No doInBackground, vamos modificar o código, conforme a Listagem 6.

...int numberOfRecords = 0;if (dataArray == null) dataArray = (JSONArray) graphObject.getProperty(“data”);

int NumeroInicial = myList.size();int NumeroFinal = myList.size() + NumeroRegistros;

if (NumeroFinal > dataArray.length()) NumeroFinal = dataArray.length();

for (int i = NumeroInicial; i < NumeroFinal; i++) {

JSONObject jsonObject = dataArray.optJSONObject(i); FacebookFriend facebookFriend = new FacebookFriend(jsonObject);

if (facebookFriend.isValid()) { numberOfRecords++;

myList.add(facebookFriend); }

Page 27: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 27

Listagem 7. Implementando o onScroll do ListView

www.lucianopimenta.net

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

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

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

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

Sobre o autor

}

isMore = (myList.size() < dataArray.length());...

Primeiro, verificamos se o dataArray é null, para que possamos carregá-lo na primeira vez. Depois, declaramos duas variáveis para pegar o inicio e o fim do laço que vai percorrer o array. O inicio será sempre o tamanho de myList, que é a lista com os amigos e suas imagens.

O final, é a soma da quantidade da lista juntamente com um número que vamos definir, que nesse exemplo será de 20 (declare NumeroRegistro). Após o laço, temos uma propriedade que indicará se teremos mais registros no ListView (declare isMore).

O restante do código é igual ao exemplo anterior. No onPostExecute va-mos modificar para que possamos verificar quando o usuário rolar o ListView, conforme o código da Listagem 7.

...list.setAdapter(new FacebookAdapter(FriendsActivity.this, myList));//posiciona o primeiro item da lista quando carregar registros (após o primeiro carregamento)if (myList.size() > NumeroRegistros) list.setSelection(myList.size() - NumeroRegistros);

list.setOnScrollListener(new AbsListView.OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {

}

@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { int loadedItems = firstVisibleItem + visibleItemCount; //verifica se esta “rolando” a lista para baixo

if ((loadedItems == totalItemCount) && isMore) { new DownloadFacebookFriendsTask().execute(); }

}});

Primeiro, ao carregar, o Listview sempre posiciona no primeiro item. Quan-do formos carregar “novos” amigos, queremos que a posição da lista, fique no primeiro item carregado da nova lista. Assim, precisamos verificar se estamos no “segundo ou mais carregamento” para então posicionar o item da lista.

No onScrollListener, verificamos a quantidade de itens para poder chamar o DownloadFacebookFriendsTask novamente e carregar mais itens da lista. Execute a aplicação. Será carregado primeiramente, os primeiros 20 registros.

Role a lista para baixo, e quando chegar no último item, será exibido a mensagem de carregamento e após, mais 20 registros serão adicionados e assim sucessivamente.

Conclusão

Vimos nesse artigo, mias um pouco da integração do Android com redes sociais, nesse caso, o Facebook. Existem muitas outras funcionalidades que podem ser implementadas. Recomendo a documentação do SDK do Facebook, está atualizada e é completa.

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

Page 28: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015

dicas the club

28

LinguagemC#-GerandoSenhasaleatoriamente

Muitas vezes temos a necessidade de gerar uma senha provisória para realizar alguma tarefa e uma das alternativas seria possuir uma rotina que faça esta tarefa. Esta dica irá possuir uma constante com todos os caracteres válidos para esta senha e uma função chamada “SenhaAleatoria”, a qual irá ter como retorno um texto contendo uma senha aleatória e de um tamanho pré-determinado. Ver listagem 01.

//Declaração da Constante

private const string Caracteres = “abcdefghijklm nopqrstuvwxyz1234567890@#!?”;

//Função Responsável por retornar a senha

public string SenhaAleaoria(int tamanho){ int valormaximo = Caracteres.Length; Random random = new Random(DateTime.Now.Millisecond); StringBuilder senha = new StringBuilder(tamanho);

for (int indice = 0; indice < tamanho; indice++)senha.Append(Caracteres[random.Next(0, valormaximo)]);

return senha.ToString();}

Exemplo de utilização em Asp.Net, Ver Imagem 01.

//Como devemos proceder para chamá-la

protected void Button1_Click(object sender, EventArgs e){ TextBox1.Text = SenhaAleaoria(6);}

Figura 01: Utilização em Asp.Net.

SQLServer-UtilizandorecursosdoSQLServerparaimportaçãodedadosdeplanilhasdoExcel

Uma das dúvidas que surgiram ultimamente em nosso suporte técnico é de como devemos proceder para realizar a importação de dados XLS (Origem de planilhas do Excel) para o banco de dados SQL Server. A partir da versão 2008 do SQL Server temos diversos recursos para esta tarefa, um deles irei abordar nesta dica rápida chamado “OPENROWSET” (um provedor de conjuntos de linhas em massa). Este provedor é acessado chamando a função OPENROWSET e especificando a opção BULK. Esta função permite acessar dados remotos conectando-se a uma fonte de dados remota, como um arquivo de dados, por meio de um provedor OLE DB. Para importar dados em massa, chame OPEN-ROWSET (BULK...) de uma cláusula SELECT...FROM dentro de uma instrução INSERT. A sintaxe básica para importar dados em massa é:

Exemplo:

INSERT ... SELECT * FROM OPENROWSET(BULK...)

Para nosso exemplo deveremos possuir uma tabela do Excel com alguns dados, como por exemplo: Código, Data, Numero e Nome. Veja exemplo na figura 01.

Figura 01: Tabela Excel.

A tabela de destino deverá possuir a mesma estrutura, ver código SQL na listagem 01.

Page 29: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 29

CREATE TABLE [dbo].[TABELA]( [CODIGO] [int] NULL, [DATA] [date] NULL, [NUMERO] [varchar](15) NULL, [NOME] [varchar](50) NULL)ON [PRIMARY]

Listagem 01.

Como o Microsoft SQL Server Management Studio (MSSMS) aberto exe-cutaremos os passos abaixo:

1-) Esta Primeira Execução deveremos realizar para configuração da pro-priedade “Show Advanced Option”. A opção 1 deverá ativá-la.

EXEC sp_configure ‘show advanced option’, ‘1’;RECONFIGURE;

2-) Já na Segunda execução definiremos 1 para “Ad Hoc Distributed Queries”

EXEC sp_configure ‘Ad Hoc Distributed Queries’, ‘1’;RECONFIGURE;

3-) Deveremos executar a Procedure de sistema chamada “master.dbo.sp_MSset_oledb_prop”, a qual iremos definir os mecanismo OLEDB.12.0.

EXEC master.dbo.sp_MSset_oledb_prop N’Microsoft.ACE.OLEDB.12.0’, N’AllowInProcess’, 1

4-) Novamente executamos esta procedure alterando o parâmetro “Di-namicParameters”.

EXEC master.dbo.sp_MSset_oledb_prop N’Microsoft.ACE.OLEDB.12.0’, N’DynamicParameters’, 1

5-) Comando para inserção dos dados da planilha para a tabela.

INSERT INTO TABELA select * FROM OPENROWSET(‘Microsoft.ACE.OLEDB.12.0’, ‘Excel 12.0;Database=D:\Planilha.xlsx;HDR=YES’, ‘SELECT * FROM [TABELA$]’)

6-) Conferindo se os dados foram exportados com sucesso

select * FROM TABELA

Delphi-ComoCriarUmaCaixadeDiálogoPerso-nalizadaUtilizandoaFunçãoCreatemessagedialog

function TCMessageDlg(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; aColor: TColor = clInfoBk): Integer;begin with CreateMessageDialog(Msg, DlgType, Buttons) do try BorderIcons := []; Color := aColor; Result := ShowModal; finally Free; end;end;

{Chamando a Função}

procedure TForm1.Button1Click(Sender: TObject);begin if TCMessageDlg(‘The Club!!!’, mtConfirmation, [mbYes, mbNo]) = mrYes then TCMessageDlg(‘OK!’, mtInformation, [mbOk], clAqua);end;

Page 30: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho201530

Delphi - Inserindomais de uma linha napropriedadeCaptiondeumBotão

{Coloque o código abaixo no evento Oncreate do Form}procedure TForm1.FormCreate(Sender: TObject);var R : TRect; N : Integer; Buff : array[0..255] of Char;

begin with BitBtn1 do begin Caption := ‘Este exemplo mostra como colocar mais de uma linha no caption de um botão’; Glyph.Canvas.Font :=

Self.Font; Glyph.Width := Width - 6; Glyph.Height := Height - 6; R := Bounds(0, 0, Glyph.Width, 0); StrPCopy(Buff, Caption); Caption := ‘’; DrawText(Glyph.Canvas.Handle, Buff,StrLen(Buff),R, DT_CENTER or DT_WORDBREAK or DT_CALCRECT); OffsetRect(R,(Glyph.Width - R.Right) div 2, (Glyph.Height - R.Bottom) div 2); DrawText(Glyph.Canvas.Handle, Buff, StrLen(Buff), R, DT_CENTER or DT_WORDBREAK); end;end;

Page 31: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015 05

Page 32: The Club - megazineexemplos práticos. O uso deste mecanismo se torna indispensável para todo o desenvolvedor que deseja aumentar a qualidade do código e do resultado final para

junho2015