Sei sulla pagina 1di 82

Sumrio

Criando meu app step-by-step Parte I ................................................................................................................. 3


Criao da App ..................................................................................................................................................... 3
Definio do Layout ............................................................................................................................................. 4
Criando o menu inicial ......................................................................................................................................... 5
Primeira codificao ............................................................................................................................................ 8
Criando o segundo FORM e testando o menu ................................................................................................... 11
Testando a app .................................................................................................................................................. 14
Concluso .......................................................................................................................................................... 15
Criando meu app step-by-step Parte II .............................................................................................................. 16
Retomando o raciocnio ..................................................................................................................................... 16
Prototipao ...................................................................................................................................................... 17
Prottipo de Usurios ........................................................................................................................................ 19
Criando uma tela de login .................................................................................................................................. 20
Construindo a classe de login ............................................................................................................................ 21
Usando a Classe Login........................................................................................................................................ 23
Modelagem de Dados ........................................................................................................................................ 24
Concluses ......................................................................................................................................................... 25
Criando meu app step-by-step Parte III .......................................................................................................... 26
Retomando o Raciocnio .................................................................................................................................... 26
Codificando a abertura do banco de dados ....................................................................................................... 28
Conectando a primeira tabela ........................................................................................................................... 29
Detalhes dos Ttulos........................................................................................................................................... 30
Concluses ......................................................................................................................................................... 32
Criando meu app step-by-step Parte IV ............................................................................................................. 33
Retomando o raciocnio ..................................................................................................................................... 33
Alterando o banco de dados .............................................................................................................................. 33
Binding de Fotos ................................................................................................................................................ 34
Errata da Parte II ................................................................................................................................................ 35
Editando um registro ......................................................................................................................................... 36
Gerando um novo registro................................................................................................................................. 38
Criando um pop-up menu.................................................................................................................................. 41
Excluindo registros............................................................................................................................................. 43
Concluso .......................................................................................................................................................... 44
Criando meu app step-by-step Estilo Parte V............................................................................................... 45
Usando um estilo mais profissional ................................................................................................................... 45
Criando um arquivo de configuraes ............................................................................................................... 46
__________________________________________________________________________________________
1

Codificando o arquivo INI .................................................................................................................................. 47


Cadastro de Preferncias ................................................................................................................................... 49
Configurando e baixo um cdigo-fonte usando Git no RAD Studio XE7 ............................................................ 50
Concluses ......................................................................................................................................................... 51
Criando meu app step-by-step DataSnap REST Parte VI .............................................................................. 52
Criando o servidor DataSnap REST..................................................................................................................... 52
Criando o servidor ............................................................................................................................................. 53
Entendendo o Servidor ...................................................................................................................................... 53
Aplicao Cliente ............................................................................................................................................... 54
Testando o retorno de mtodos ........................................................................................................................ 56
Concluses ......................................................................................................................................................... 56
Criando meu app step-by-step Reflection Parte VII ..................................................................................... 57
Criando a tabela no banco de dados Firebird .................................................................................................... 57
Reflection do FireDAC Configurao do servidor DataSnap ............................................................................ 57
Preparando o cliente para acesso ...................................................................................................................... 60
Preparando o Sincronismo................................................................................................................................. 60
Pausa para mtodos annimos.......................................................................................................................... 61
Retomando o raciocnio ..................................................................................................................................... 61
Concluses ......................................................................................................................................................... 61
Criando meu app step-by-step ArrayDML Parte VIII .................................................................................... 62
Criando meu app step-by-step ArrayDML Parte VIII .................................................................................... 62
Entendendo o conceito...................................................................................................................................... 63
Otimizando Memria ......................................................................................................................................... 65
Concluses ......................................................................................................................................................... 67
Criando meu app step-by-step Botes de Hardware Parte IX...................................................................... 68
Botes de Hardware .......................................................................................................................................... 68
Concluso .......................................................................................................................................................... 71
Criando meu app step-by-step Sincronismo Parte X Final ........................................................................ 72
Tutorial: Criando meu app step-by-step Sincronismo Parte X ..................................................................... 72
Editando e Adicionando registros no cliente ..................................................................................................... 74
Editando os dados ............................................................................................................................................. 76
Atualizando e Selecionando fotos...................................................................................................................... 78
Excluindo do servidor ........................................................................................................................................ 78
Excluindo no cliente versus Excluindo no servidor ............................................................................................ 79
ApplyUpdates no servidor ................................................................................................................................. 79
Enviando novos registros ................................................................................................................................... 80
Concluso .......................................................................................................................................................... 80

__________________________________________________________________________________________
2

Criando meu app step-by-step Parte I


O desenvolvimento de aplicaes mveis utilizando Delphi tem gerado muito pano pra manga em comunidades
Delphi nas redes sociais. Com o interesse cada vez maior, de programadores novos ou experientes, em desenvolver
apps com a ferramenta, surgem tambm as dvidas. Muitas comuns como o simples fato de navegar entre telas de um
app ou ainda dvidas mais avanadas como o uso de Bluetooph com Delphi em iOS e Android. Muito bem, baseado
nisso resolvi criar alguns posts com orientaes e um passo-a-passo explicando as principais dvidas encontradas pela
internet.
Nesse primeiro post vamos comear do incio:
1.
2.
3.
4.

Criao da app;
Criao do layout;
Navegao entre as abas;
Navegao entre formulrios.

Requisitos:
1. Delphi XE5 ou superior;
2. Aparelho Android;
3. Aparelho iPhone com iOS 7 ou superior (caso deseje testar no iOS);
Obs 1. Serei bastante detalhista no incio para abranger iniciantes e experts.
Obs 2. Usarei nesses primeiros posts o RAD Studio XE6, devido ao novo recurso de formulrios Master que terei que
explicar em um segundo momento separado.

Criao da App
Vamos comear, evidentemente, abrindo o Delphi e criando a aplicao salvando-a em um diretrio de nossa
preferncia. Utilize o menu File > New > Multi-Device Application Delphi (no XE7, em XE5 e 6 o nome do menu
diferente, apenas verifique o correto). (Figura 1)

Figura 1. Incio da aplicao

__________________________________________________________________________________________
3

Na tela que se abre, escolhemos o layout inicial de nossa aplicao. No se preocupe com isso agora, podemos mudar
com o tempo. Portanto, vamos escolher a opo Blank Application.

Somos levados ao primeiro Form de nossa app e vamos chama-la de frmMain (Principal). Existem milhares de tcnicas
diferentes para criar nosso layout e a navegao do aplicativo, mas nesse caso vou mostrar como eu tenho criado meus
aplicativos em minha empresa, assim fica como sugesto.
Para quem j est utilizando o Delphi XE7, deve estar visualizando algo diferente na IDE. So os layouts Master. Agora
possvel criar um layout principal e deixar que a IDE selecione o correto para cada dispositivo no momento de abertura
de nosso form. Mas isso assunto para outros posts, por enquanto vamos nos focar em celulares Android e iOS de 4.
Para isso selecione Android 4 Phone caso esteja no XE7, os demais leitores que esto em verses anteriores utilizem
as opes Google Nexus 4 ou Samsumg Galaxy S2/S4, etc. (Figuras 2 e 3)
Criando meu app step-by-step
Figura 2. Definio de Layout no XE7

Figura 3. Definio de Layout XE4,5 e 6


Feito isso o que vamos comear a fazer entender ao certo como nossa app ir se comportar. Tive a ideia de criar um
app para controle de locadora (Quem nunca fez um sistema de locadora ao fazer um curso de programao, no
mesmo? ;)), pois j estamos familiarizados com algumas das tabelas e informaes que uma locadora precisa ter para
funcionar.
Nesse primeiro momento faremos a criao de nossas listas sem o uso de banco de dados, ou seja, aprenderemos a
usar o esquema de Prototipao do Delphi criando dados fictcios para visualizarmos o funcionamento do app.
Salvemos o projeto ento. Na propriedade Name do formulrio insira o texto frmMain (sem as spas) e salve o
formulrio usando File > New > Save As D o nome de UntMain e salve-o no diretrio que desejar. Em seguida salve
o projeto usando File > New > Save Project As Dei o nome de LocadoraDelphi.dproj

Definio do Layout
Muito bom. A primeira coisa a se definir, na minha opinio, desenhar como a aplicao dever se comportar. Eu me
utilizo de vrias tcnicas para isso. Como no sou designer, mas tenho alguma noo de desenho, comprei um bloco
de folhas A3 tipo flipcharting onde costumo desenhar, rusticamente claro, o fluxo da minha aplicao. (Figura 4).

__________________________________________________________________________________________
4

Figura 4. Folha A3 para desenho

Para quem no tem a mnima noo de desenho, existem inmeras ferramentas no mercado que ajudam nesse
quesito. Mas enfim, no nosso foco aqui. Vamos desenhar na nossa mente mesmo o que desejamos que nosso app
tenha. Proponho as seguintes telas:
Login e Senha;
Lista de Ttulos;
Lista de Usurios/Clientes;
Lista de Ttulos Alugados;
Alugar: Tela para definir o aluguel para um cliente;
Baixar Ttulo Alugado;
A ideia que o app seja utilizado pelo administrador da ocadora como se fosse a extenso de seu programa de uso no
desktop da loja, onde o cara poder consultar rapidamente algumas informaes sobre o ttulo. Nossa tela default ser
a Lista de Ttulos que dever abrir logo que de incio. Faremos um Login e Senha utilizando Parse.com como backend
de banco de dados para facilitar e aprender a usar o servio;
Teremos tambm um menu no estilo Facebook Mobile que se popularizou bastante, ou seja, abriremos as opes
tocando em um boto com Detalhes e o menu se abrir na lateral.

Criando o menu inicial

Para criamos o menu inicial, vamos utilizar um TLayout e um TListBox. Ambos devem ser colocamos no formulrio e
NO um dentro do outro. Adicione primeiro o TLayout e faa as seguintes configuraes:
Name: lytMain;
Align: Client;
Agora adicione um TListBox no Form e ento faremos uma srie de mudanas nele conforme mais abaixo.
#Dica: Caso tenha dificuldades em selecionar o Form principal j que o TLayout ficou por cima de tudo, apenas clique
no TLayout e pressione 1x o ESC. Isso far com que o Form seja selecionado.
E caso j tenha adicionado o TListBox dentro do TLayout, basta acessar a caixa de estrutura e mover o TListBox para
cima do Form;
Configure o TListBox como segue:
Name: lstMnuMain
Align: Cient
GroupKind: Grouped
StyleLookup: transparentlistboxstyle
Agora que configuramos as principais propriedades, precisamos adicionar os itens que sero nossos Itens de Menu.
Agruparemos em categorias, por isso utilizamos a propriedade GroupKind para dar um aspecto mais profissional
acrescido do StyleLookup como Transparent.
Obs. Em dado momento faremos a personalizao da aplicao incluindo um layout mais customizado

__________________________________________________________________________________________
5

Clique agora com o boto direito no TListBox e escolha Items Editor para acessarmos o gerenciador de itens
do ListBox. No ComboBox direita da caixa, encontramos os tipos de itens que podemos adicionar. Usaremos sempre
dois tipos (Figura 5):
TListBoxGroupHeader: Cabealho do Grupo;
TListBoxItem: Item

Figura 5. Tipos de Item de ListBox

Figura 6. Ordem os menus


Adicione 2 (dois) TListBoxGroupHeader e 4 (quatro) TListBoxItem e coloque-os na ordem da Figura 6. Cada item
do ListBox possui suas propriedades, isso significa que podemos utilizar a propriedade Text como Caption do nosso
menu e ainda outras propriedades como ItemData para adicionar um boto Acessory e uma imagem para ele.

__________________________________________________________________________________________
6

#Dica: Em Mobile, os botes (figuras) que ficam direita do item na lista so chamados de Acessory (Acessrio). Servem
para indicar se o item possui um Mais Informaes, Sub Detalhe ou ainda um Check para por exemplo indicar
que o item est selecionado para alguma ao.
#Dica: Procure observar outros aplicativos e seguir os conceitos padres de cada sistema operacional, pois o principal
fator para que uma aplicao tenha sucesso : Usabilidade. Lembre-se que o usurio j est acostumado com certos
comportamentos nos apps que j utiliza no dia-a-dia.
Configuraremos somente os itens de nosso interesse. Clique no ListBoxItemGroupHeader1 e configure como a seguir:
Name: lstgrpListas
Text: Cadastros
O segundo grupo, modifiquei como a seguir:
Name: lstgrpConfig
Text: Configuraes
Agora configure o TListBoxItem1 como a seguir:
Name: lstitTitulos
Text: Ttulos
ItemData > Acessory: More
Repita os passos anteriores para configurar os demais itens de menu. Nosso menu final ter que ficar semelhante
a Figura 7. Os Names,respectivamente, so:
lstitTitulos
lstitUsuarios
lstitTitulosAlugados
lstitLogin

Figura 7. Menu final


Observe que no colocamos todos os itens de menu na tela nesse primeiro momento. Vamos comer o boi por partes
como dizem meus conterrneos. Muito bom! Nossa mecnica para carregar cada Form ser a seguinte:
1. Para cada Lista, teremos um TForm com suas prprias funcionalidades, barras de navegao, etc;
2. No utilizaremos Show ou ShowModal, ao contrrio. Criaremos o TForm no momento oportuno e carregaremos ele
dentro do TLayout principal em nosso frmMain utilizando um AddObject. Dessa forma temos controle total sobre todos
os forms abertos.
Por conta do segundo item que colocamos o menu (ListBox) e o layout (TLayout) dentro do formulrio e no um dentro
do outro como mencionado anteriormente. Nosso lytMain ser um mero espectador, receber dentro dele todos os
objetos (Forms) que precisarmos navegar.
Para ter certeza que fez as configuraes corretas, seu projeto dever se parecer com a Figura 8 que se refere a
caixa Struture do Delphi.

__________________________________________________________________________________________
7

Figura 8. Caixa Structure

Primeira codificao

Perfeito at aqui e sei que esto eufricos para codificar tudo. Ento mos a obra. Primeiro criaremos mtodos para
mostrar e ocultar o menu. Para isso, teremos que adicionar alguns elementos visuais ao formulrio para termos uma
aparncia mais interessante.
Adicione ao formulrio 2 (dois) novos componentes. 1 TFloatAnimation e 1 TRectangle. Eles devem ficar DENTRO do
lytMain. O componente de animao deve receber o Name = AnimateDrawer. J o TRectangle precisa ser configurado
como a seguir:
Name: recBackground
Opacity: 0,5
Fill.Color : Black
PropertyName: Position.X
Essas configuraes daro um aspecto mais profissional. Se desejar conferir a estrutura dos componentes novos,
observe a Figura 9.

Figura 9. Aspecto final do menu


Vamos ao cdigo dos mtodos agora. Crie duas novas Procedures na seo Private do Form como na Listagem 1:
__________________________________________________________________________________________
8

Listagem 1. Cdigo dos novos mtodos


?
1
2

procedure HideMenu;
procedure ShowMenu;

Pressione Ctrl + Shift + C para criar o escopo de cada mtodo e vamos ao cdigo de cada um conforme a Listagem 2.
Listagem 2. Cdigo dos mtodos criados para Mostrar e Ocultar o Menu
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

procedure TfrmMain.HideMenu;
begin
//Posiciona o ListBox de menu fora da viso
lstMnuMain.AnimateFloat('Position.X', -Self.ClientWidth);
AnimateDrawer.StartValue := Self.ClientWidth - 40;
AnimateDrawer.StopValue := 0;
AnimateDrawer.Start;
end;
procedure TfrmMain.ShowMenu;
begin
AnimateDrawer.StartValue := 0;
AnimateDrawer.StopValue := Self.ClientWidth - C_MnuEspaco;
AnimateDrawer.Start;
//Reposiciona o menu principal
lstMnuMain.AnimateFloat('Position.X', 0);
//Mostra o retngulo preto sobre a lista ativa
ShowBackground(Self.lytMain, CancelMenu);</pre>
<pre>end;

No primeiro mtodo, HideMenu, posicionamos o ListBox do menu para fora da rea de visualizao utilizando uma
animao atravs do mtodo AnimateFloat. Esse mtodo um dos que mais gosto de usar. bem simples e
praticamente todos os objetos Firemonkeypossuem. Basta passar a propriedade que se deseja animar no primeiro
parmetro e o novo valor no segundo parmetro. Nesse caso usamos Position.X com o valor -Self.ClientWidth, que far
o componente se descolar para a esquerda.
Em seguida animamos o layout usando o nosso componente TFloadAnimation. O cdigo ao meu ver dispensa
comentrios assim como o mtodo ShowMenu que exatamente o inverso. Apenas observe que reposicionamos o
ListBox na posio 0 (Zero).
Teremos ainda que criar outros mtodos que nos ajudaro a controlar melhor o menu. Retorne as
sees Private e Public do form e adicione os novos mtodos conforme a Listagem 3.
Listagem 3. Outros mtodos de controle do menu
?
1
2
3
4
5
6
7
8
9
10

private
{ Private declarations }
procedure HideMenu;
procedure ShowMenu;
procedure CancelMenu(Sender: TObject);
public
{ Public declarations }
procedure ShowHideMenu;
procedure ShowForm(AObject: TFmxObject);
procedure ShowBackground(AParent: TFmxObject; AOnClick: TNotifyEvent = nil);
procedure HideBackground;
end;

Vamos as explicaes:

CancelMenu: Ser necessrio para esconder o retngulo opaco da tela e ocultar o menu;

ShowHideMenu: Controla a visibilidade do menu;


ShowForm: Indicaremos ao formulrio Main quem dever estar visvel ou invisvel;
ShowBackground e HidBackground: Responsveis por mostrar e ocultar o retngulo;
Pressione Ctrl + Shift + C para criao dos escopos e codifique como na Listagem 4.
Listagem 4. Mtodos de controle do menu
?
1
2
3

procedure TfrmMain.CancelMenu(Sender: TObject);


begin
HideBackground;

__________________________________________________________________________________________
9

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

ShowHideMenu;
end;
procedure TfrmMain.ShowHideMenu;
var
Position : single;
begin
{Verifica a posio atual do menu e mostra ou oculta conforme necessrio}
Position := Self.ClientWidth - 40;
case Self.lytMain.Position.X = Position of
true : HideMenu;
false : ShowMenu;
end;
end;
procedure TfrmMain.ShowForm(AObject: TFmxObject);
var
I : Integer;
begin
HideBackground;
for I := 0 to Pred(Self.lytMain.Children.Count) do
TControl(Self.lytMain.Children[I]).Visible :=
TControl(Self.lytMain.Children[I]) = TControl(AObject);
end;
procedure TfrmMain.ShowBackground(AParent: TFmxObject; AOnClick: TNotifyEvent);
begin
//Atualiza o evento OnClick do retgulo com a ao enviada por parmetro.
///Isso far com que saibamos a tela (ou ao) que deve ser mostrada ao clicar no retngulo
recBackground.OnClick := AOnClick;
recBackground.Parent := AParent;
recBackground.BringToFront;
//Modifica a transparncia do retngulo e anima a transparncia
recBackground.Opacity := 0;
recBackground.Visible := True;
recBackground.AnimateFloat('opacity', 0.5, 0.1);
end;
procedure TfrmMain.HideBackground;
begin
recBackground.AnimateFloat('opacity', 0, 0.1);
recBackground.Visible := False;
end;

Vamos
as
explicaes
de
cada
mtodo
iniciando
por CancelMenu. Esse
mtodo
apenas
chama HideBackground e ShowHideMenuforando o retngulo opaco desaparecer e checando se o menu est aberto
ou fechado para saber para onde temos que ir.
Em seguida ShowHideMenu. Atravs da varivel Position conseguimos detectar qual o posicionamento do Menu (nosso
ListBox, lembre-se). A varivel recebe a largura da tela atual, ou seja, funcionar tanto com celulares quanto com
tablets e na horizontal ou vertical. E subtramos 40 px para evitar que a tela (listagem) atual suma completamente da
viso do usurio. Com base na posio do menu, decidimos se o mostramos ou ocultamos.
ShowForm ser responsvel por receber o objeto (Form, Layout, TabControl) alvo e deixa-lo visvel para o usurio. A
ideia simples. Quando codificarmos o OnClick de cada Item de Menu, faremos um AddObject dentro do nosso
lytMain, em seguida chamamos ShowForm para ocultar todos os outros formulrios e mostrarmos somente o atual.
Isso necessrio, pois nosso ListBox est configurado como como Transparente. Se deixarmos visveis os demais forms,
corremos o risco de sobrepor as telas.
Por fim ShowBackGround e HideBackGround. No primeiro mtodo, recebemos o Parent do objeto que est sendo
carregado, para que o retngulo opaco fique sobre ele, assim teremos um aspecto esmaecido do form quando o
menu estiver aberto. Tambm recebemos um evento OnClick caso desejarmos que ao clicar no retngulo algo
acontea. Por fim trazemos ele para frente e configuramos sua opacidade, visibilidade e a animao para aparecer.
Reparem que estou usando novamente o mtodo AnimateFloat (dessa vez no retngulo) passando como parmetro a
propriedade opacity e os valores 0.5 e 0.1 nos parmetros seguintes.
O 0.5 o novo valor da opacidade, para deixa-lo levemente transparente. O 0.1 o tempo que levar para a animao
ocorrer.

__________________________________________________________________________________________
10

Criando o segundo FORM e testando o menu


A essa altura do campeonato, provavelmente conseguiremos compilar normalmente nossa aplicao sem problemas.
Ento, agora vamos criar um segundo formulrio para testar se nosso menu e nossa mecnica est funcionando
perfeitamente.
Crie um novo form usando File > New > Firemonkey Mobile Form Delphi e marque a opo HD FireMonkey Form. Por
fim clique em Ok, para finalizar (Figuras 10 e 11). Agora temos um segundo formulrio que ser usando para nossa Lista
de Ttulos.

Figura 10. Criao do novo Form

Figura 11. Confirmao do novo Form

Vamos apenas configurar as propriedades mais bsicas e o layout principal do formulrio. Na Parte II do post faremos
a prototipao da janela para evitar que esse post fique ainda maior.
Primeiro adicione um ToolBar no formulrio e mude sua propriedade Name para toolTitulos. Inclua em seguida um
TLayout ao formulrio e chame-o de lytTitulos. Tambm configure-o para que fique com alinhamento Client (Align =
Client). Ns carregaremos o lytTitulos dentro do lytMain no formulrio principal.
Dentro do TLayout adicione um TabControl e configure suas propriedades como a seguir:
Name: tabctrlTitulos
TabPosition: Bottom
__________________________________________________________________________________________
11

Clique com o boto direito no TabControl e adicione uma nova aba usando o item Add TTabItem. Nessa TabItem (que
chamamos de Aba) colocaremos nossos controles para acesso a base de dados. Por enquanto vamos adicionar apenas
um TLabel com alinhamento Client e o Text igual a Listagem de Ttulos. Modifique tambm a
propriedade TextSettings.HorzAlign para Center, apenas para sinalizar quando carregarmos essa janela no dispositivo
ou emulador.
Para fechar, adicione um TSpeedButton dentro da ToolBar. Ele ser nosso boto voltar. Configure-o como a seguir:
Name: spbBack
StyleLookup: detailstoolbutton
Align: Left
Margins.Left: 8
Teremos ento uma aparncia semelhante a imagem da Figura 12.

Figura 12. Aparncia do formulrio Ttulos


A nica codificao por hora nesse Form fazer a chamada ao mtodo ShowHideMenu do formulrio principal. Isso
mesmo! Ns vamos fazer um Use Unit do formulrio principal em nossa Listagem de Ttulos. Clique em File > Use Unit e
adicione a unit UntMain na seo Implementation do form.
Em seguida clique duas vezes no nico boto dessa tela e adicione a linha de cdigo a seguir:
?
1

frmMain.ShowHideMenu;

Fazendo isso, ns chamamos o mtodo ShowHideMenu que se encarregar de mostrar o menu novamente para que
o usurio possa entrar em outra janela.
Uma ltima alterao no cdigo-fonte da janela, retire a declarao da varivel com a instncia do form, no
precisaremos dela. Localize a seo implementation e apague as linhas como a seguir:
?
1
2

var
frmTitulos: TfrmTitulos;

__________________________________________________________________________________________
12

Retornamos agora para o formulrio principal para fazer a as devidas chamadas e abrir a nossa tela de ttulos.
Acesse File > Use Unit e adicione o formulrio de ttulos a seo interface do form principal. Agora selecione
o lstitemTitulos e adicione o cdigo da Listagem 5ao evento OnClick.
Listagem 5. Cdigo do evento OnClick para abertura da tela Listagem de Ttulos
?
1
2
3
4
5
6
7
8
9

if not Assigned(FTitulos) then


FTitulos := TfrmTitulos.Create(Self);
{Adiciona o Layout de Pedidos ao Layout Principal que controla tudo}
lytMain.AddObject(FTitulos.lytTitulos);
{Deixa todos os layouts invisveis e deixa o layout alvo visvel}
ShowForm(FTitulos.lytTitulos);
if Sender <> Self then
ShowHideMenu;

O que estamos fazendo aqui bem simples na verdade. Primeiro verificamos se h alguma instncia do formulrio de
ttulos na memria. Note que usamos uma varivel FTitulos para isso e logo em seguida criamos o Form frmTitulos. A
variveis FTitulos precisa ser declarada na seo Private do form principal, como abaixo:
?
1
2
3
4

...
private
FTitulos: TfrmTitlos;
...

Na seqncia adicionamos o TLayout lytTitulos (Form Titulos) ao TLayout lytMain do formulrio principal. Por fim
chamamos ShowFormpara fazer com que o form se torne visvel. A ltima instruo evita que o menu aparea caso
quem esteja chamando o mtodo seja o prprio form principal.
Estaria pronto para testar nesse momento, mas ainda vamos fazer umas configuraes. Lembram-se que nosso
formulrio de ttulos ser aberto assim que a app inicializar? Pois bem, teremos que codificar ento o
evento OnCreate do form principal. Para isso selecione o Form e clique duas vezes no evento OnCreate e codifique
como na Listagem 6.
Listagem 6. OnCreate do form principal
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

procedure TfrmMain.FormCreate(Sender: TObject);


begin
{Layout Escuro Global}
recBackground.Visible
:= False;
recBackground.Align
:= TAlignLayout.Contents;
{Modifica a largura do ListBox para a mesma do formulrio, pois o mesmo est como Align = None}
lstMnuMain.Width
:= Self.ClientWidth;
lstMnuMain.Position.X := -Self.ClientWidth;
//Traz para frente o layout principal evitando sobreposio de listas
lytMain.BringToFront;
lstitTitulosClick(Sender);
end;

Precisamos de algumas personalizaes aqui. Primeiro ns deixamos o retngulo invisvel e mudamos seu alinhamento
para Contents,ou seja, ao contedo, equivalente a opo Client.
#Dica: A diferena entre os alinhamentos Client e Contents, que Contents encobre tambm as barra de status do
aparelho, normalmente visvel na parte superior.
Em seguida ajustamos o menu principal e trazemos o layout para frente de todos os objetos. Por fim, chamamos o
mtodo lstitTitulosClick para forar a abertura do formulrio Listagem de Ttulos.
E a ltima codificao acontece no evento OnClose do formulrio principal. Foramos a liberao da instncia do
formulrio de ttulos caso esteja aberto.
?
1
2

if Assigned(FTitulos) then
FTitulos.DisposeOf;

Ateno para o mtodo DisposeOf. No utilize em Mobile o mtodo Free ou FreeAndNil, pois acabam entrando na fila
do ARC(Gerenciamento de Memria do dispositivo). O DisposeOf fora o FREE da varivel imediatamente. Em outras
palavras, variveis ou objetos devem ser liberados de memria usando esse mtodo.

__________________________________________________________________________________________
13

Testando a app
bvio que depois de chegarmos at aqui, estamos curiosos para testar a aplicao. Ento hora de contar um
segredo. No exatamente um segredo, mas uma dica til. No vamos perder tempo compilando
para iOS ou Android, ou ainda nos simuladores/emuladores. Vamos testar direto no Windows, pois todas as
funcionalidades at aqui codificadas funcionam perfeitamente no Windows.
Para isso, acesse o Project Manager sua esquerda (caso no tenha mudado as configuraes do Delphi) e clique com
o boto direito em cima de Target Platforms. Clique em Add Platform e escolha Win32 na janela que aparece (Figuras
13 e 14).

Figura 13. Adio de plataforma

Figura 14. Plataforma Win32


Agora basta clicar duas vezes na plataforma e executar a aplicao.
#Dica: Caso no precise debugar a aplicao, selecione Release em Build Configurations, pois mais rpido o deploy,
inclusive dos aparelhos.
Se tudo correr bem, teremos telas semelhantes as figuras seguintes:

__________________________________________________________________________________________
14

Concluso
Assim como mencionado desde o incio, existem milhares de maneiras diferentes de criar layouts e navegao em uma
app Mobile. Essa apenas uma delas. Vimos nesse post como criar nosso primeiro menu no estilo Facebook e como
interagir com mais de um form na mesma aplicao.
No prximo post, veremos como prototipar a aplicao. Criaremos uma lista de ttulos utilizando LiveBindings e o
componente PrototypeBindSource assim como o uso de DataModule.

Uma atualizao. Existe uma constante mencionada no mtodo ShowMenu, C_MnuEspaco. Troquem ela pelo valor
40. Esse o espao que a listagem ficar afastada quando o menu estiver aberto.
?
1
2
3
4
5
6
7
8
9
10
11
12

procedure TfrmMain.ShowMenu;
begin
AnimateDrawer.StartValue := 0;
AnimateDrawer.StopValue := Self.ClientWidth - 40;
AnimateDrawer.Start;
//Reposiciona o menu principal
lstMnuMain.AnimateFloat('Position.X', 0);
//Mostra o retngulo preto sobre a lista ativa
ShowBackground(Self.lytMain, CancelMenu);
end;

__________________________________________________________________________________________
15

Criando meu app step-by-step Parte II

1.
2.
3.
4.
5.
6.
7.
8.
9.

A primeira parte desse tutorial publicada uma semana atrs (Link aqui) teve como principal objetivo iniciar uma srie
de artigos em formato passo-a-passo mostrando algumas das principais tcnicas e funcionalidades existentes na
ferramenta de desenvolvimento RAD Studio XE6. O objetivo do tutorial construir um aplicativo totalmente a partir
do zero e que seja compatvel com iOS e Android.
No post anterior fomos capazes de:
Criar o app;
Criar o layout inicial;
Desenvolver a navegao base entre as abas;
Desenvolver a navegao base entre os formulrios da aplicao.
Nessa segunda parte, veremos como criar nosso primeiro prottipo do aplicativo que nos ser til para entender e
definir os aspectos gerais do app. Tambm veremos:
Criao do primeiro prottipo funcional;
Criao de dados fictcios com LiveBindings;
Ligao dos dados fictcios do LiveBindings com o objetos de tela, tais como TListView;
Montagem das demais telas do sistema utilizando LiveBindings;
Uso do servio Parse.com;
Criao de Classe para Login e Senha na nuvem bem como outras funcionalidades;
Login e Senha on-line;
Modelagem da nossa base de dados SQLite;
Introduo ao SQLite e sugesto de ferramentas.

Requisitos:
Assistir ao vdeo: FireUI Novo Form Designer RAD Studio XE7
Assistir ao vdeo: TMultiView no RAD Studio XE7
Assistir ao vdeo: Aula complemento Criando meu app step-by-step
Leitura: Como cadastrar e validar login no servio Parse.com usando RAD Studio XE6

1.
2.
3.
4.

Retomando o raciocnio
Assim como mencionado no incio desse artigo, no captulo anterior iniciamos a criao de nosso app a partir do RAD
Studio XE6/Delphi XE6. Nesse captulo vamos dar continuidade ao nosso desenvolvimento, mas agora com um pouco
mais nfase em dados e processos reais.
Para comear, espero que tenham assistido aos vdeos indicados na rea de requisitos, pois so importantes para
darmos continuidade. Na Figura 1, logo abaixo, vemos como ficou nosso formulrio principal, frmMain, depois da
migrao para o RAD Studio XE7.

__________________________________________________________________________________________
16

Figura 1. Aplicativo migrado para RAD Studio XE7


O que fizemos aqui foi incluir o novo componente TMultiView ao formulrio para que tenhamos um menu lateral
automtico sem esforo de codificao, assim podemos nos concentrar em coisas ainda mais importantes.
Nessa segunda etapa faremos o LiveBindings da lista de Ttulos para que tenhamos algum dado para exibio. Ento
mos na massa.

Prototipao
Vamos nos concentrar na primeira janela de nosso app, Lista de Ttulos. Abra esse Form e adicione a ele um
componente do tipo TPrototypeBindSource da paleta LiveBindings.
#Dica: Para encontrar os componentes de maneira mais rpida, digite o nome do componente no campo de pesquisa
da Tool Palette.

Esse componente nos d plena condio de criar uma lista fictcia com dados para preenchimento de nossa lista. Agora
adicione tambm um componente do tipo TListView da paleta Standard e d o nome de lsvTitulos a ele. Configure suas
propriedades como a seguir:
Name: lsvTitulos
ItemAppearance.ItemAppearance: MultiRightDetail
ItemAppearanceObjects.ItemObjects.Image.Visible: True
#Dica: O TListView padro do Delphi no possui a opo MuiltiRightDetail, por isso assista ao vdeo TMultiView no RAD
Studio XE7 para ver como fazer a instalao desse componente.
Agora clique duas vezes no componente PrototypeBindSource1 e vamos adicionar os campos relacionados ao nosso
prottipo. Com o dilogo aberto, clique no nico boto disponvel no momento para adicionar o primeiro campo. Uma
nova caixa de dilogo ser aberta com duas colunas: Generator e Type. Aqui temos todo tipo de dado que pode ser
gerado aleatoriamente pelo Delphi para simular um banco de dados.
Inicie usando o item ContactBitmaps. Clique nele e no campo logo acima, FieldName, digite o valor FOTO. Esse ser o
campo para receber a foto do ttulo a ser alugado, ou seja, a capa do DVD.
Repita esse passo adicionando os campos como na Tabela 1:
Generator
ContactBitmaps
ContactNames

Type
ftBitmap
ftStrings

Field Name
Foto
Titulo

__________________________________________________________________________________________
17

ContactNames
AlphaColors
Tabela 1. Campos do prottipo de ttulos

ftStrings
ftUInteger

SubTitulo
CodTitulo

O resultado ser semelhante a Figura 2 onde conseguimos visualizar todos os campos da nossa lista fictcia.

Figura 2. Tabela com campos fictcios do prottipo


Feche a janela e faremos agora a ligao dos campos aos respectivos itens no TListView via LiveBindings. Acesse o
Object Inspector e localize no rodap dele o item Bind Visually. Caso no o encontre, clique com o direito no formulrio
e localize o Bind Visually no pop-up. Ns veremos uma tela semelhante a Figura 3.

Figura 3. Bind Visually

O Bind Visually localiza todos os controles da tela e possibilita que liguemos um ao outro para que tenhamos uma
atualizao automtica sem a necessidade de codificao. Em nosso exemplo usaremos apenas os componentes
TListView (lsvTitulos) e o TPrototypeBindSource (PrototypeBindSource1). O restante pode ser ocultado clicando com o
direito nele e escolhendo a opo Hide Element(s).
#Dica: Selecione todos os componentes que ficaro ocultos. Clique em cada item com a tecla Ctrl selecionada. Em
seguida clique em um dos controles selecionados com o boto direito do mouse e ento Hide Element(s).
Note que no lsvTitulos temos as propriedades representadas no Bind Visually:
Item.Text
Item.Detail1
Item.Detail2
Item.Detail3
Item.Bitmap

__________________________________________________________________________________________
18

Entre outras, claro. O que vamos fazer agora ligar cada campo da nossa lista as respectivas propriedades. Por isso,
arraste, em primeiro lugar, o Astersco do Prototype a propriedade Synch. Em seguida siga a lista abaixo:
Foto >>> Item.Bitmap;
CodTitulo >>> Item.Detail3
Titulo >>> Item.Detail1
SubTitulo >>> Item.Detail2
Teremos algo semelhante a Figura 4, inclusive com o formulrio j mostrando dados fictcios.

Figura 4. Ligao do LiveBindings


Perceba que um novo componente foi adicionado ao formulrio, o LiveBindList. Esse o componente que possui o link
de cada propriedade e seus campos. Dessa forma j temos uma lista pronta.

Prottipo de Usurios

Para a janela de usurios, crie um novo formulrio usando o menu File > New > Multi-Device Form Delphi. Modifique
sua propriedade Name para frmUsuarios e salve-o como UntUsuarios. Inclua tambm um TLayout com o nome de
lytUsuarios e alinhe-o como Client. Coloque uma ToolBar dentro do Layout e logo em seguida um SpeedButton dentro
da ToolBar. Configure-o como a seguir:
Name: spbBack
Align: Left
Margins.Left: 8
StyleLookup: detailstoolbutton
Adicione a ele um TListView com propriedade de alinhamento ao Cient. Repita todos os passos da sesso anterior para
criar um prottipo com uma lista de usurios. Siga a Tabela 2 com os nomes de campos e tipos de dados.
Generator
ContactBitmaps
ContactNames
ContactNames
AlphaColors
Tabela 2. Campos do Prottipo de Usurios

Type
ftBitmap
ftStrings
ftStrings
ftUInteger

Field Name
Foto
Nome
Apelido
CPF

__________________________________________________________________________________________
19

Criando uma tela de login

Faremos uso agora do servio de banco de dados na nuvem chamado Parse.com. Desde a verso anterior do Delphi,
ns contamos com componentes do tipo BaaS (Backend as a Services). Esse tipo de servio tem se popularizado
bastante ultimamente.
No incio desse artigo, na sesso Requisitos, voc encontra um link para um artigo que escrevi falando justamente
disso, portanto no vou me estender muito nesse tpico. Tomarei como verdade que voc j entrou no servio
Parse.com, cadastrou-se e criou sua classe Users no servidor deles. No se preocupe, no tutorial informado em
requisitos j h todas as informaes necessrias para o cadastramento no servio.
A partir daqui, crie um novo form que iremos usar como janela de login. D o nome a essa janela de frmLogin e salvea como UntLogin.pas. Repita os passos das telas anteriores para montar o layout base, ou seja, insira um TLayout e
coloque-o como alinhamento ao Client. Dentro dele uma ToolBar e um SpeedButton com o nome spbBack.
Agora iremos montar um box para digitao de usurio e senha. O design fica por sua conta, mas nesse tutorial irei
usar um componente TCalloutPanel da paleta Standard. Alinhe-o como Vertical e aumente ou diminua sua altura de
acordo com seu gosto.
Dentro dele insira um SpeedButton mudando seu Text para Enviar e seu alinhamento para Bottom. Agora coloque
um ListBox com 3 (trs) linhas e seu alinhamento como Client. Modifique a propriedade e ItemHeight para algo em
torno de 40 ou 50 pixels. Isso aumentar a altura das linhas do ListBox.
O primeiro item do Listbox ter sua propriedade Text alterada para Registrar-se. E coloque tambm um componente
do tipo TSwitchda paleta Standard. Configure-o como a seguir:
Name: swtRegistrar
Align: Right
Margins.Right: 10
A segunda e terceira linha contero os Edits para digitao de login e senha. Altere a propriedade Text de ambos para
Usurio e Senha, respectivamente. Insira um TEdit em cada linha alinhando-os direita com margem direita de
10px. Os nomes deles podem ser edtUsuario e edtSenha. O edtSenha precisa ter sua propriedade Password para True.
Localize a paleta de compnentes BaaS Client e adicione o componente BackendUser mudando seu nome
para bkendUsuarios. Localize agora o componente TParseProvider e adicione-o a tela dando o nome de ppUsuarios.
O primeiro componente adicionado o componente que se conectar on-line ao servio e validar nosso usurio e
senha. J o ppUsuarios receber as informaes de nosso cadastro no servio, tais como as chaves de acesso
criptografaras. Por isso, conecte o bkendUsuarios ao ppUsuarios usando a propriedade Provider.
Em ppUsuarios alimente as propriedades ApplicationID, RestApiKey e MasterKey com os valores de sua conta no
servio Parse.com. Em caso de dvidas onde obter tais informaes, leia o artigo recomendado em requisitos. Confira
a Figura 5 como nossa tela dever se assemelhar.

Figura 5. Modelo de tela de login

__________________________________________________________________________________________
20

Construindo a classe de login


Para que nosso sistema torne-se mais profissional, vamos dar incio a criao de uma classe de Login que ser utilizada
futuramente por toda a aplicao. A explicao base simples.
1. Criaremos mtodos para efetuar o Login, Logout e Registrar um novo Usurio no Parse.com;
2. Guardaremos a sesso do usurio para que possamos validar mais tarde se ele est ou no logado.
Para isso entre em File > New > Unit Delphi. Salve essa Unit com o nome Login.pas. No meu caso criei uma pasta no
projeto para guardar todas as nossas classes. Criei com o nome Lib. Agora copie e cole desse tutorial, o cdigo
da Listagem 1 em sua nova Unit.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

unit Login;
interface
uses
{$Region 'FireDac'}
FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, FireDAC.UI.Intf,
FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys, FireDAC.Phys.SQLite,
FireDAC.Stan.ExprFuncs, FireDAC.FMXUI.Wait, Data.Bind.EngExt,
Fmx.Bind.DBEngExt, FireDAC.Comp.UI, Data.Bind.Components, Data.Bind.DBScope,
Data.DB, FireDAC.Comp.Client, FireDAC.Comp.DataSet,
{$EndRegion}
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.Variants, FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs,
FMX.StdCtrls, FMX.MobilePreview, System.Rtti,
REST.Backend.ServiceTypes, REST.Backend.MetaTypes, System.JSON,
REST.OpenSSL, REST.Backend.ParseProvider, REST.Backend.Providers,
REST.Backend.ServiceComponents;
type
TLogin = class
private
FSession
: TBackendEntityValue;
FSessionStarted : Boolean;
FObjBackEndUsers: TBackendUsers;
public
constructor Create;
destructor Destroy;
function Login(AUser, APassword: string): Boolean;
function Logout: Boolean;
function SignUp(AUser, APassword: string): Boolean;
published
property Session
: TBackendEntityValue read FSession
write FSession;
property SessionStarted : Boolean
read FSessionStarted
write FSessionStarted;
property ObjBackEndUsers: TBackendUsers read FObjBackEndUsers write FObjBackEndUsers;
end;
implementation
end.

Listagem 1. Escopo da classe


Na sesso Uses estamos adicionando toda as units necessrias para a codificao de nossa classe. Peo ateno apenas
agora na definio da classe.
Criamos em Interface a classe TLogin sem nenhuma herana, ou seja, TLogin = class. Declaramos FSession do
tipo TBackendEntityValueque receber a sesso do usurio logado. E uma varivel para marcarmos como True/False
sempre que o usurio, respectivamente, fizer login ou logout.
Em seguida declaramos os mtodos Create e Destroy para controlarmos a criao e destruio da classe e tambm o
estado de algumas variveis. Na seqncia criamos 3 (trs) mtodos todos devolvendo Boolean, assim podemos testar
na chamada se o mtodo foi executado com sucesso. Explicao dos mtodos:
Login: Receberemos como texto o Usurio e Senha digitados nos campos na janela de login. Verificamos se o login e
senha so vlidos e inicializamos a sesso usando a varivel FSession.
Logout: Apenas limpamos a informao da FSession retornando ao sistema que o usurio no est mais on-line.
SingnUp: Usaremos esse mtodo para cadastrar o usurio on-line sempre que ele marcar o item Registrar-se, ou seja,
usurio novo.

__________________________________________________________________________________________
21

Criamos tambm duas propriedades, Session e SessionStarted que dispensam comentrios. Apenas uma informao
relacionada a Orientao a Objetos. Internamente nossa classe atualiza as propriedades criadas atravs das
variveis FSession e FSessionStarted. Mas por fora da classe fazemos referncia pela propriedade, ou seja:
?
1
2

if MeuObjetoLogin.SessionStarted then
//usurio logado, chama tela XXX

Pressione Ctrl + Shift + C para criar o escopo dos mtodos e codificarmos. Uma propriedade/varivel que no expliquei
propositadamente foi FObjBackEndUsers. Essa propriedade ser responsvel por receber a referncia ao
objeto BackEndUserscolocado na tela de login. Assim nossa classe fica genrica e podemos us-la em qualquer lugar.
Na Listagem 2 voc pode ver todo o cdigo de cada mtodo.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

constructor TLogin.Create;
begin
inherited Create;
{$IFDEF DEBUG}
FSessionStarted := True;
{$ELSE}
FSessionStarted := False;
{$ENDIF}
end;
destructor TLogin.Destroy;
begin
inherited Destroy;
end;
function TLogin.Login(AUser, APassword: string): Boolean;
var
tmpSession : TBackendEntityValue;
begin
try
FObjBackEndUsers.Users.LoginUser(AUser, APassword, tmpSession);
FSession
:= tmpSession;
FSessionStarted := True;
Result
:= True;
except on E:Exception do
begin
{ Erro de usurio e senha }
if E.Message.Equals('Parse Error: invalid login parameters (101)') then
raise Exception.Create('Usurio ou Senha invlidos!');
Result := False;
end;
end;
end;
function TLogin.Logout: Boolean;
begin
try
FObjBackEndUsers.Users.Logout;
FSessionStarted := False;
Result
:= True;
except on E:Exception do
begin
{ Erro de usurio e senha }
if E.Message.Equals('Parse Error: invalid login parameters (101)') then
raise Exception.Create('Usurio ou Senha invlidos!');
Result := False;
end;
end;
end;
function TLogin.SignUp(AUser, APassword: string): Boolean;
var
Session : TBackendEntityValue;
begin
try
{ Valida se nome de usurio j existe na base }
FObjBackEndUsers.Users.QueryUserName(AUser, Session);
if Session.ObjectID.IsEmpty then
begin

__________________________________________________________________________________________
22

60
61
62

{ Cria o usurio j fazendo login na sesso }


FObjBackEndUsers.Users.SignupUser(AUser, APassword, nil, FSession);
ShowMessage('Usurio e Senha cadastrado com sucesso!');
FSessionStarted := True;
Result
:= True;
end
else
begin
ShowMessage('Nome de Usurio j existe. Por favor escolha outro!');
Result := False;
end;
except on E:Exception do
raise Exception.Create('Erro de internet!' + E.Message);
end;
end;

Listagem 2. Codificao final da classe


Vamos entender agora o que estamos fazendo na classe comeando pelo mtodo construtor Create. Nele estamos
usando uma diretiva de compilao para no atrapalhar nossos testes no futuro. Caso a aplicao tenha sido compilada
em Debug, marcamos a sesso como Iniciada, assim no seremos obrigados a digitar usurio e senha toda hora. Caso
contrrio, o sistema j inicia como sesso no iniciada.
Em seguida temos o mtodo Login recebendo usurio e senha em formato Texto (String). Nosso cdigo aqui bem
simples. Chamamos a funo LoginUser presente no objeto BackendUsers. Passamos para a funo o Usurio e a Senha
passados por parmetro bem como uma varivel temporria de Sesso declarada nesse mtodos. A
funo LoginUser valida o usurio e a senha e devolve a informao para a sesso temporria. Caso o usurio e a senha
no existam on-line, uma exceo ser gerada com o erro: Parse Error: invalid login parameters (101). Existem milhares
de formas de testar, mas acabei fazendo na maneira mais simples possvel.
Caso o usurio e senha tenham sido validados com sucesso, as variveis FSession e FSessionStarted so atualizadas e
devolvemos Result := True informando que o mtodo obteve sucesso.
Logout o mtodo mais simples. Apenas chamamos a funo de mesmo nome contida no objeto BackendUsers e
atualizamos as respectivas variveis.
Por fim, SignUp, acredito que o mtodo mais inteligente da classe. Primeiro ns chamamos a
funo QueryUserName passando o usurio recebido e uma sesso temporria. Se a Sesso temporria estiver vazia
na propriedade ObjectID, significa que o usurio passado no existe na base. O ObjectID na verdade o campo de
chave primria da tabela Users no servio Parse.com e alimentado sempre que cadastramos um novo usurio.
Estando vazia, ento chamamos o mtodo SignupUser passando o usurio e senha informados nos campos da janela.
Assim o usurio ser cadastrado e logo em seguida iniciamos a sesso do usurio.
Caso o ObjectID esteja preenchido, significa que o usurio j existe no banco, ento pedimos ao usurio para informar
um apelido diferente.

Usando a Classe Login


Perfeito! At aqui nenhum problema. Agora precisamos usar a classe, ou seja, efetivamente chamar os mtodos
necessrios para efetuar o login. A primeira providncia criar a classe em runtime e como precisaremos dela em
vrios lugares, vamos cria-la na abertura do sistema. Acesse o evento OnCreate do formulrio principal e digite o cdigo
abaixo:
?
1

FLibLogin := TLogin.create;

Na sesso Public do form adicione a varivel FLibLogin do tipo TLogin (usada no cdigo anterior) e d um Use
Unit no Login.pasadicionando a unit ao Uses da Interface. Assim passaremos a partir de agora a usar a unit da Classe.
Nosso formulrio principal o primeiro a ser iniciado, portanto o nico que far referncia direta a Login.pas por
enquanto. para acessar as propriedades da classe, usaremos algo como:
?
1

frmMain.FLibLogin.PROPRIEDADE (ou mtodo)

Retorne agora a nossa janela de Login, frmLogin. Aqui precisaremos apenas codificar o boto de login, speLogin. Digite
nele o cdigo abaixo:
?
1
2

frmMain.FLibLogin.ObjBackEndUsers := bkendUsuarios;
case swtRegistrar.IsChecked of

__________________________________________________________________________________________
23

3
4
5

true : frmMain.FLibLogin.SignUp(edtUsuario.Text, edtSenha.Text);


false : frmMain.FLibLogin.Login(edtUsuario.Text, edtSenha.Text);
end;

Imagino que j tenham entendido ;). Caso o Swtich esteja marcado, significa que o usurio deseja cadastrar-se no
sistema, portanto chamamos o mtodo de cadastro da nossa classe, caso contrrio nosso Login. Perceba que apenas
chamamos os mtodos e no fazemos desvios, ou seja, o correto seria:
Caso o usurio consiga se cadastrar ou fazer o login, devemos chamar o click do menu Titulos para que carreguemos a
Listagem de Ttulos ou poderamos chamar qualquer tela.
Para no nos estendermos mais nesse tpico, deixo a cargo do leitor fazer os respectivos desvios.
Obs. Na primeira linha do cdigo alimentamos a propriedade ObjBackendUsers passando como referncia o objeto em
rela.

Modelagem de Dados
Para que possamos prosseguir com nosso aplicativo, vamos iniciar tambm nesse artigo a modelarem de nosso banco
de dados local, ou seja, no dispositivo. Para isso vamos utilizar um banco de dados bastante utilizado o SQLite.
O SQLite apenas um dos bancos de dados que podem ser utilizados em dispositivos mveis. Tambm possvel
usarmos IBLite, uma verso reduzida do Intebase da Embarcadero. Para saber mais sobre SQLite, voc pode acessar o
site http://www.sqlite.org que possui uma vasta documentao.
Com ele podemos realizar diversas tarefas, pois apesar de compacto, um banco bastante completo.
Existem milhares de ferramentas na internet para fazer a manuteno e criao de bancos SQLite e uma delas
o SQLite
Expert e
pode
ser
baixado
em www.sqliteexpert.com.
Existem
basicamente
duas
verses, Express e Professional e claro, utilizado a verso Express que gratuita e j ajuda bastante. Tomarei ele como
base ento para nosso artigo.
Outra ferramenta importante para mantermos uma documentao de nosso banco o DIA, uma ferramenta de
modelagem FREE, simples e objetiva. Ele pode ser encontrado e baixado em http://dia-installer.de. Minha sugesto
baixar a verso Full, pois existe a verso Portable no baixaki.com.br, mas no legal.
Acesse a ferramenta DIA abra-a em seu equipamento. No entraremos em detalhes sobre o DIA, ento resumirei suas
caractersticas.
Com o DIA aberto, Figura 6, observe na barra lateral a opo Fluxograma. Clicando nessa opo e em seguida
em Outras Folhaspodemos ver que h inmeros fluxogramas que podemos utilizar para desenhar nossa soluo. Utilize
a opo Bancos de Dados, assim ns podemos incluir nossas entidades. Por enquanto vamos criar somente a tabela de
Ttulos.

Figura 6. DIA Modelagem


Arraste um objeto do tipo Entidade para a rea branca e clique duas vezes nela para abrir a caixa de propriedades.
Nessa janela inclusa o nome da nossa tabela, TITULOS e ento clique em Atributos.
Nessa rea podemos incluir todos os campos da tabela. Comece incluindo como na Tabela 3.

__________________________________________________________________________________________
24

Campo
Type
Tamanho
ID_TITULO
Integer
TITULO
String
30
SUBTIULO
String
50
ANO_LANCAMENTO
Integer
Tabela 3. Tabela TITULOS do banco de dados
A aparncia de nossa entidade dever se parecer com a Figura 7.

Especial
AutoInc / Chave Primria
No Nulo
No Nulo

Figura 7. Entidade TITULOS


A partir de agora, faremos sempre a modelagem de dados de nossa app atravs dessa ferramenta para criar nossas
entidades e deixar sempre uma documentao atualizada.
Vamos agora replicar isso no SQL Expert criando o banco e a tabela. Abra a ferramenta e clique em File > New >
DataBase. Informe o caminho e o nome do banco de dados. Minha sugesto que salvemos o banco no mesmo
diretrio da aplicao em uma pasta com o nome Database. O nome do banco de dados poder ser Locadora.sqlite. O
restante dos campos podem ser deixados como Default.
Em seguida clique com o direito no nosso banco de dados e em seguida em New Table. Em Table Name digite TITULOS.
Logo abaixo, voc encontra algumas abas onde podemos incluir nossos campos, ndices, chaves estrangeiras, etc. Bem
abaixo encontraremos o boto Add, para criar um novo campo.
Clique em Add e adicione o primeiro campo, ID_TITULO do tipo INT. Ns vamos controlar o auto incremento da tabela
atravs de triggers no prximo artigo, portanto no se preocupe por enquanto. Continue criando a tabela utilizando
nossa entidade na modelagem. Observe a Figura 8 como dever ser concluda a criao da tabela TITULOS.

Figura 8. Tabela TITULOS criada.


Na prxima fase de nossa srie de artigos, aprofundaremos melhor no banco de dados e faremos a ligao do banco
ao nosso sistema utilizando FireDAC.
Salve o banco de dados e o diagrama de modelagem.

Concluses
Muito bem. Nessa segunda etapa de nosso aplicativo conseguimos dar passos importantes. Criamos uma classe para
efetuarmos o Login e Senha no sistema. Iniciamos a criao do banco de dados local e fizemos, claro, a migrao do
aplicativo da verso RAD Studio XE6 para XE7.

__________________________________________________________________________________________
25

Criando meu app step-by-step Parte III

1.
2.
3.
4.

No post anterior iniciamos uma das partes mais importantes de nosso aplicativo mobile com RAD Studio, o banco de
dados. Aprendemos a iniciar a criao de nosso banco utilizando o SQLite, banco bastante popular em aplicaes
mveis, utilizando para isso o aplicativo Free SQLite Expert bem como o DIA para modelagem de nossas entidades.
Nesse tutorial daremos foco para o uso de banco de dados em nosso aplicativos. Criaremos as novas tabelas e
ligaremos em nossas listagens. Em resumo no post anterior fomos capazes de:
Migrar nossa aplicao de Delphi XE6 para XE7;
Recriar o menu lateral utilizando o novo componente TMultiView;
Criar uma tela inicial de login;
Criar nosso primeiro banco de dados SQLite;
A terceira parte desse tutorial ser um pouco mais curta, mas rica em detalhes. Vermos a seguir:
Criao do DataModule principal;
Configurao dos principais componentes de acesso ao banco de dados;
Criao dos mtodos de listagem de Titulos e Detalhes dos Titulos;
Montagem das telas funcionais.

Requisitos:
Leitura: Tutorial: Criando meu app step-by-step Parte II
Assistir ao vdeo: TDevRocks Binding vs TListViews

1.
2.
3.
4.

Retomando o Raciocnio
Assim como mencionando anteriormente, iniciamos a criao de nosso banco de dados SQLite no SQLite Expert. Nessa
parte vamos enriquecer um pouco mais nosso sistema que por enquanto s tem uma tabela, TITULOS. Os atributos da
tabela podem ser vistos na Figura 1.

Figura 1. Tabela TITULOS


Nota-se que criamos um campo chamado ID_TITULO, que receber, evidentemente, um ID auto numrico para
representar o registro. Existem n possibilidades para se fazer um numerador, inclusive
com Triggers e StoredProcedures no banco, mas eu prefiro ter o controle da situao e fazer isso direto no cdigofonte. Por isso criaremos uma funo para nos retornar o ID do ttulo.
Assim como em aplicaes Desktop, possvel criar DataModules para separar nossos componentes visuais de
componentes de acesso a dados. Inicie essa etapa entrando em File >> New > Other e escolhendo a opo Data Module
no item Delphi Files. D o nome a esse Data Module de DM e salve sua unit como UntDM.pas.
Usaremos a partir daqui os componentes da paleta FireDAC, tais como FDConnection e FDQuery. O primeiro
componente a entrar no ar ser o TFDConnection, insira um no DM e renomeie-0 para fdcConexao. Aps isso clique
duas vezes nesse componente e observe a caixa de dilogo que se abre (Figura 2).

__________________________________________________________________________________________
26

Figura 2. Dilogo de configurao do banco


Nessa janela somos capazes de fazer todo tipo de configurao relacionada ao banco a ser conectado. Na parte superior
encontramos o campo Driver ID e Connection Definition Name. Em Driver ID podemos ver que o FireDAC compatvel
com diversos bancos, entre eles DB2, Firebird (FB), Interbase (IB), SQLServer (MSSQL), Oracle (ORA), entre outros
tantos. Mas no se confunda. Atualmente os nicos bancos de dados que podem ser executados no dispositivo mvel
(at o fechamento desse artigo, claro) so IBLite que uma verso reduzida do Interbase para Mobile e o SQLite, que
estamos tratando aqui. O fato, por exemplo, de termos acesso a Firebird, no significa que ele rodar em nosso
dispositivo, o que tem causado bastante confuso em algumas pessoas.
Se voc j tem um vnculo com nosso SQLite atravs do Data Explorer do Delphi (Janela ao lado direito do Delphi) ento
podemos v-lo e seleciona-lo nessa caixa. Por hora apenas selecione SQLite em Driver ID.
Em seguida a nica configurao que faremos informar o caminho e nome do banco de dados ao FireDAC na
propriedade Database. Em nosso exemplo, o banco est na pasta raiz do cdigo-fonte na pasta Database. Algo como:
C:\tutorial\Database\Locadora.sqlite
Observe onde voc salvou seu banco para poder indicar o caminho correto. Para ter certeza que est tudo bem, clique
em Test para ver se conecta-se ao banco. Uma mensagem como na Figura 3 dever aparecer.

Figura 3. Conexo com sucesso


Provavelmente se compilarmos o app nesse momento, nenhum problema ser detectado, mas provvel que
recebamos algumas mensagens de erro ao executar o app no Windows ou no dispositivo. Isso porque ainda precisamos
declarar algumas units ou, mais fcil, incluir dois novos componentes que fazem o papel final de configurao do app.
Insira um FDGUIxWaitCursor e n FDPhysSQLiteDriverLink. No necessria nenhuma configurao adicional. So na
verdade os componentes que fazem o link final com o banco, no entrarei em detalhes. Por fim, desative a propriedade
Login Prompt do fdConexao.

__________________________________________________________________________________________
27

Agora, vamos fazer nossa primeira Query. Insira u FDQuery e d o nome a ela de qryTitulos. Insira em sua propriedade
SQL o seguinte cdigo SQL.
?
1
2
3
4
5
6
7

SELECT
ID_TITULO,
TITULO,
SUBTITULO,
ANO_LANCAMENTO
FROM
TITULOS

No entrarei em detalhes sobre instrues SQL, tomarei como verdade que todos tem o mnimo de noo sobre o SQL.
Estamos fazendo aqui uma simples seleo de dados, apenas trazendo os campos da tabela. Caso deseje, tambm
possvel clicar duas vezes no componente Query e abrir a janela de edio de SQL. Inclusive possvel fazer o teste de
retorno de dados para verificar se a instruo est correta.
Aps ter digitado a instruo, clique com o direito no componente e selecione Fields Editor e em seguida clique com o
direito e selecione Add all fields para adicionar todos os campos da tabela.
At aqui, se voc j conhece o mnimo de Delphi, no h novidades. Se preferir acesso campo a campo e modifique a
propriedade DisplayFormat inserindo nomes mais amigveis para cada campo da tabela.

Codificando a abertura do banco de dados


Evidentemente temos que distribuir e abrir o arquivo de banco de dados sempre que a aplicao se abre. Para isso
costumo codificar diretamente no evento OnCreate do Data Module usando o cdigo da Listagem 1.
?
1 procedure TDM.DataModuleCreate(Sender: TObject);
2 begin
3
with fdcConexao do
4
begin
5
{$IF DEFINED (IOS) || (ANDROID)}
6
Params.Values['DriverID'] := 'SQLite';
7
try
8
Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.sqlite');
9
Connected := True;
10
except on E: Exception do
11
begin
12
raise Exception.Create('Erro de conexo com o banco de dados!');
13
end;
14
{$ENDIF}
15
16
{$IFDEF MSWINDOWS}
17
try
18
Params.Values['Database'] := 'P:\tutoriais-tdevrocks\Curso-Completo\Parte III - SQLite\Database\Locadora.sqlite';
19
Connected := True;
20
except on E: Exception do
21
begin
22
raise Exception.Create('Erro de conexo com o banco de dados!');
23
end;
24
{$ENDIF}
25
end;
26 end;

Listagem 1. Abertura do banco de dados


O que estamos fazendo aqui algo relativamente simples. Vamos l. Primeiro note que utilizei a palavra reservada
WITH. Para quem no conhece, os iniciantes claro, essa palavra reservada permite que no precisemos mais digitar
repetidas o nome de um objeto no bloco, exemplo:
Ao invs de usarmos toda hora:
?1 fdcConexao.Params.Values.['DriverID']...
2
3

fdcConexao.Params.Values['Database']...
fdcConexao.Connected := True;

Ns simplesmente envolvemos o bloco inteiro com um:


?1 with COMPOENTE do
Para mais de um componente, podemos incluir vrgulas:
?1 with fdcConexao, qryTitulos, frmPrincipal do

__________________________________________________________________________________________
28

...

Perceba inclusive que inclumos no exemplo anterior, frmPrincipal, ou seja, tambm so aceitos formulrios.
Muito bem, estamos atualizando o parmetro DriverID com o nome do driver de nosso banco, ou seja, SQLite. Em
seguida atualizamos o parmetro com o nome caminho completo do banco. Ateno apenas para alguns detalhes.
Estamos usando Diretivas de Compilao para desviar o cdigo de acordo com a plataforma.
?1 {$IF DEFINED (IOS) || (ANDROID)}
Se for iOS ou (||) Android usamos TPath.Combine e TPath.GetDocumentsPath. Ambos os mtodos pertencem ao
namespace System.IOUtils, portanto declare essa unit na seo Interface da unit.
TPath.Combine: Responsvel por concatenar duas strings de endereo. Ele j faz o trabalho de descobrir, por exemplo,
qual barra utilizar, j que h diferena entre iOS, Android e Windows;
TPath.GetDocumentsPath: Descobre qual o endereo da pasta Documents no dispositivo mvel.
Sempre utilize esses dois mtodos para buscar e concatenar diretrios no Mobile.
Por fim de tudo, conectamos ao banco de dados usando um Connected := True;
Envolvemos tudo isso em um TryExcept para evitar que algum problema acontea sem que possamos notificar o
usurio.

Conectando a primeira tabela


hora de colocarmos dados reais no nosso aplicativo, por isso faremos agora o Binding da primeira tabela real,
TITULOS. Na primeira parte desse artigo, j inclumos um FDQuery ao Data Module e codificamos a instruo SQL para
trazer os dados de TITULOS. Agora precisamos ler essas informaes em u TListView. Para isso, abra nosso formulrio
de ttulos frmTitulos.pas.
Faa com que ele tenha vnculo com nosso Data Module usando o menu File >> Use Unit e escolhendo o DM. Ao fazer
isso, conseguiremos visualizar tanto o TListView quando o BindSource na janela Bind Visually (Figura 4).

Figura 4. Bind Visually de Ttulos


Alm disso, teremos que tomar outra providncia: abrir a tabela Ttulos. Faremos isso, por enquanto, no menu,
portanto retorne ao frmMain, clique duas vezes no ListBoxItem correspondente ao nosso Menu Ttulos e clique duas
vezes para visualizarmos o cdigo-fonte.
Adicione o cdigo das linhas a seguir:
?
1
2

DM.qryTitulos.Active := False;
DM.qryTitulos.Active := True;

Estamos fechando e abrindo novamente a tabela para forar um refresh. No esquea de fazer um Use Unit nesse
form, j que ele ainda no enxerga nosso Data Module.
Em outro momento faremos uma codificao para formar o DisposeOf dos formulrios no visveis em tela, evitando
que tenhamos memria desnecessria sendo desperdiada. Nesse momento transferiremos o cdigo de abertura das
queries para o Form Create de cada tela.
Antes de testar a aplicao, acesse o menu Project >> Options e em Form modifique a ordem de criao do frmMain e
do DM como mostrado na Figura 5.. Estamos ainda sem foto para os ttulos, que devero aparecer ao lado esquerdo
do TListView.

__________________________________________________________________________________________
29

Figura 5. Ordem de criao dos formulrios

Detalhes dos Ttulos

Montaremos agora uma aba para mostrar os detalhes do nosso Ttulo. Para isso adicione uma nova aba ao TabCtrl de
Clientes clicando com o boto direito nele e em seguida em AddTabItem. Nessa TabItem, que chamaremos de
tbitemDetalhes, adicione um TListBox. Adicione somente duas linhas (Itens) nesse ListBox. O primeiro deles, altere a
altura para 105px. Adicione um TImage com o nome de imgFoto e alinhe-0 a esquerda modificando tambm suas
margens para 8px em todos os lados.
Ainda na primeira linha do ListBox, adicione um TLayout e dentro dele 2 (Labels). Eles sero nosso Ttulo e SubTtulo
respectivamente. Eles devem receber o Name e o Text como abaixo, assim como outras propriedades:
Label Ttulo
Name: lblTitulo
Text: lblTitulo
StyleLookup: listboxitemlabel
Align: Top
Margins.Right: 8
Margins.Top: 8
Label SubTitulo
Name: lblSubTitulo
Text: lblSubTitulo
StyleLookup: listboxitemdetaillabel
Align: Client
Margins.Bottom: 8
Margins.Right: 8
Margins.Top: 8
A segunda linha receber apenas e Text = Ano Lanamento.
O ListBox dever ficar com a propriedade Align igual a Client, mas antes de fazer isso adicione uma ToolBar. Dentro
dela adicione um SpeedButton e d o nome a ele de spbVoltar e o Text como Voltar. Modifique seu StyleLookup para
backtoolbutton e a propriedade Left do Margins para 8px. No evento OnClick desse button, apenas escreva:
?
1

tabctrlTitulos.Previous;

Esse boto ser responsvel por voltar a listagem de ttulos. Agora sim marque o ListBox como Client e vamos ver o
resultado. Nossa janela dever possuir uma aparncia semelhante a da Figura 6.

__________________________________________________________________________________________
30

Figura 6. Exemplo de tela de detalhes


O que acabamos de fazer foi criar o layout de nossa janela de detalhes de uma maneira mais profissional. Agora, basta
entrar novamente na Bind Visually e ligar os respectivos lables aos campos da base de dados. Apenas um detalhe aqui.
A segunda linha do ListBox ter a propriedade Text ligada ao campo ANO_LANCAMENTO no Binding, entretanto essa
propriedade no aparece por Default, portanto localize o item de listbox na janela de Binding e clique no boto
reticncias dele, assim uma nova caixa de dilogo ser aberta e basta marcarmos a propriedade Text e clicar em OK. O
nico que ainda no ser ligado o imgFoto, pois ainda no temos um campo de foto no banco de dados. Veja como
todos os campos ficam ligados na Figura 7.

Figura 7.
Tambm no queremos que as abas na parte inferior sejam mostradas para o usurio final, ento deixaremos elas na
tela apenas em tempo de projeto para nos ajudar a desenhar e fazer as devidas manutenes. Mas em runtime
sumiremos com elas assim como marcaremos como default a aba de Listagem. Entre no evento OnCreate desse form
e digite o cdigo a seguir:
?
1
2

tabctrlTitulos.TabPosition := TTabPosition.None;
tabctrlTitulos.ActiveTab
:= tbitemLisTitulos;

__________________________________________________________________________________________
31

Bem simples no? Estamos mudando a propriedade TabPosition para None, assim as abas no aparecero. E tambm
configuramos a ActiveTab como sendo a listagem. Retorne agora para a aba principal e selecione o evento OnItemClick
do TListView. Digite o cdigo para passar para a aba de Detalhes:
?
1

tabctrlTitulos.Next;

Um ltimo retoque. Se executarmos agora o aplicativo, veremos que no lugar de Ano Lanamento aparece apenas o
Ano, e o texto some. Ento clique duas vezes no componente BindinsList1 e em seguida selecione o link correspondente
ao Item de ListBox do Ano de Lanamento, provavelmente ser o ltimo. Pressione F11 para abrir o Object Inspector
e selecione o campo CustomFormat. Digite na propriedade o texto a seguir:
?
1

'Ano Lanamento: ' + %s

Isso far com que concatenemos a palavra Ano Lanamento com o valor gravado na tabela, ou seja, o ano
propriamente dito.
Perfeito, com isso finalizamos nossa tela de detalhes. Execute o aplicativo e veja como ficou. Observe no Vdeo 1 como
ficou nossas alteraes nessa terceira parte.

Concluses
Nessa terceira parte de nosso tutorial, vimos como implementar o uso de tabelas reais de um banco SQLite para
carregar informaes em um TListView. Vimos tambm como facilmente criar um Layout para mostrar os detalhes de
um item do ListView, nesse caso um Item selecionado pelo usurio final.
Na prxima etapa, veremos como fazer o primeiro CRUD (Funes de Incluso, Excluso e Alterao de Dados) no
banco de dados.

__________________________________________________________________________________________
32

Criando meu app step-by-step Parte IV

1.
2.
3.
4.
5.

Chegamos a Parte IV de nosso Tutorial: Criando meu app step-by-step em RAD Studio XE7. No captulo anterior, mais
curto que os demais, aprendemos a montar nossa tela de Listagem de Ttulos conectada em dados reais atravs de um
banco de dados SQLite. Ns fizemos a navegao, vinculamos o banco ao projeto e deixamos tudo preparado para
iniciarmos a parte de Incluso, Excluso e Alterao de ttulos. Confira abaixo:
Criao do DataModule principal;
Configurao dos principais componentes de acesso ao banco de dados;
Criao dos mtodos de listagem de Titulos e Detalhes dos Titulos;
Montagem das telas funcionais.
Nessa nova etapa veremos como implementar o CRUD (Create, Read, Update e Delete, ou seja, Insero, Leitura,
Atualizao e Excluso) em nosso aplicativo. Vejamos a pauta:
Criao de campo do tipo imagem na tabela de Ttulos;
Criao de mtodo para auto-numerar ID de Ttulos;
Binding da imagem com as listagem e detalhes do Ttulo;
Incluso, Alterao e Excluso de Ttulos;
Seleo de fotos da biblioteca ou cmera;

Requisitos
Leitura: Tutorial: Criando meu app step-by-step parte III;
Assistir ao vdeo: TDevRocks Binding vs TListViews

1.
2.
3.
4.

Retomando o raciocnio
Nossa sesso Retomando o raciocnio de hoje tem a ver com o que fizemos at o presente momento. No captulo
anterior ns iniciamos, como dito anteriormente, com uma parte crucial: incluso de dados reais. Entretanto deixamos
para trs duas coisas:
1. Auto-numerao do ID de Ttulos;
2. Criao do campo Foto;
A foto ser usada para mostrar a capa do ttulo, DVD, em questo. Tanto no TListView quanto em detalhes. E no caso
do ID do ttulo, como vamos ter outros numeradores, vamos criar uma funo no DataModule que receba a tabela e o
nome do campo e devolvemos j um Integer com o ID, assim poderemos reutilizar a function em outras tabelas quando
necessrio.

Alterando o banco de dados


Vamos comear abrindo o SQLite Expert e alterando nossa tabela TITULOS. Clicando em TITULOS acesse a aba Design
e em seguida clique em ADD na parte inferior para adicionarmos um novo campo. Digite FOTO no campo Name e
IMAGE no Type para escolhermos o tipo de dado (Figura 1).

Figura 1. Criando o campo FOTO


__________________________________________________________________________________________
33

Feito isso, teremos que alterar a instruo SQL que traz os campos. Por isso, retorne ao Delphi e acesse o DataModule
(DM) para que possamos modificar o componente qryTitulos. Selecione a propriedade SQL e clique duas vezes nela e
inclua o campo FOTO na instruo assim como na Listagem 1.
?
1
2
3
4
5
6
7
8

SELECT
ID_TITULO,
TITULO,
SUBTITULO,
ANO_LANCAMENTO,
FOTO
FROM
TITULOS

Listagem 1. Select alterada de TITULOs


Agora precisamos adicionar o novo campo a lista de campos Fields Editor do qryTitulos. Para isso clique com o boto
direito do mouse do componente e selecione Fields Editor. Com o direito na pequena janela que aparece, clique em
Add Fields. Isso far com que o campo FOTO aparea.
#Dica: Certifique-se de que abriu o banco Locadora.sqlite correto no SQLite Expert e que o banco apontado na
propriedade Database no FDConnection tambm esteja apontado para o banco que sofreu a alterao, do contrrio
nosso campo no aparecer na janela.
Muito bom at aqui, precisamos somente fazer o binding do novo campo com os componentes de imagem da tela de
ttulos frmTitulos.

Binding de Fotos
H quem prefira salvar as fotos em uma pasta especfica. Tambm prefiro, mas depende muito do tipo de aplicao.
Nesse caso prefiro salvar direto no banco, j que seria mais chato fazer o binding com as fotos soltas no device. Esse
processo to simples quanto o que fizemos no captulo anterior.
Acesse a janela frmTitulos e em seguida acione o Bind Visually. Selecione o TListView correspondente a lista de ttulos
e observe que ele possui um item chamado Item.Bitmap em sua lista de campos na janela Binding. Ligue o campo FOTO
a esse item. Do mesmo modo, mude para a aba de Detalhes e ligue o campo FOTO a propriedade Bitmap do TImage
que colocamos para receber a foto.
#Dica: Caso no aparea a propriedade Bitmap em qualquer dos casos, clique nas reticncias do objeto que deseja
fazer a ligao do Binding, e localize a propriedade desejada na caixa de dilogo. Marque-a e ento ela aparecer no
bind.
Pronto! A primeira parte do binding est finalizada. O que precisamos fazer agora preparar a parte de codificao
para que possamos possibilitar mudar a foto do item na lista. Veja as ligaes dessa sesso na Figura 2.

__________________________________________________________________________________________
34

Figura 2. Binding de fotos

Errata da Parte II
Na Parte II ns fizemos a codificao para vincular nosso banco de dados em runtime no evento OnCreate do
DataModule, mas acabei publicando um erro na utilizao de diretivas de compilao que s notei com o incio dos
testes nesse captulo. No OnCreate utilizamos a seguinte linha:
?
1
2
3

[...]
{$IF DEFINED (IOS) || (ANDROID)}
[...]

Quando na verdade o correto seria:


?
1
2
3

[...]
{$IF DEFINED(IOS) OR DEFINED(ANDROID)}
[...]

Alguns leitores tambm reclamaram que ao passar pela linha Connected := True, o banco dados no abre e ainda indica
um erro na aplicao, que est relacionado a uma configurao no passada no captulo III. Clicando duas vezes do
componente FDConnection (fdConexao), repare que em nossas configuraes existe uma propriedade chamada
OpenMode que est setada como CreateUTF8. Troque-a para ReadWrite. Isso se faz necessrio, pois estamos
distribuindo o banco de dados SQLite e no criando-o em runtime.
Em outras palavras, j temos o banco de dados criado e faremos a distribuio dele quando fecharmos a aplicao para
a loja ou para nossos testes no device. Para que no fique totalmente confuso, observe a Listagem 2 que contm o
cdigo completo corrigido.

__________________________________________________________________________________________
35

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

procedure TDM.DataModuleCreate(Sender: TObject);


var
sPath: String;
begin
with fdcConexao do
begin
{$IF DEFINED(IOS) OR DEFINED(ANDROID)}
Params.Values['DriverID'] := 'SQLite';
Params.Values['OpenMode'] := 'ReadWrite';
try
sPath := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.sqlite');
Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.sqlite');

Connected := True;
except on E: Exception do
begin
ShowMessage(E.Message);
end;
end;
{$ELSE}
try
Params.Values['Database'] := 'CAMINHO_DO_BANCO_DE_DADOS\Database\Locadora.sqlite';
Connected := True;
except on E: Exception do
begin
ShowMessage(E.Message);
end;
end;
{$ENDIF}
end;
end;

Listagem 2. Cdigo do evento OnCreate do DataModule corrigido


Fonte de estudo clique aqui.

Editando um registro

H inmeras maneiras de fazemos a edio dos dados em tela, portanto faremos a princpio na maneira mais simples
e objetiva possvel. V at a aba Detalhes do Ttulo e adicione trs novos speedbuttons. Eles faro o trabalho de Editar,
Salvar e Cancelar uma edio. Configure-os como a seguir:
Name: spbEditar
StyleLookup:
Align: Right
Margins.Right: 8px
Text: Editar
Visible: False

Name: spbSalvar
StyleLoockup: donetoolbutton
Align: Right
Margins.Right: 8px
Text: Salvar
Visible: False

Name: spbCancelar
StyleLookup: deletetoolbutton
Align: Left
Margins.Left: 8px
Text: Cancelar
Visible: False
Note que todos os nossos botes possuem a propriedade Visible segada como False. Isso porque vamos deixa-los como
visveis de acordo com a situao. Criaremos um mtodo para fazer esse trabalho. Por isso crie uma nova procedure
na seo Public do formulrio e codifique como na Listagem 3.

__________________________________________________________________________________________
36

?
1
2
3
4
5
6
7

procedure TfrmTitulos.AtualizarBotoes;
begin
spbVoltar.Visible
:= (DM.qryTitulos.State = dsBrowse);
spbEdicao.Visible
:= (DM.qryTitulos.State = dsBrowse);
spbCancelar.Visible := (DM.qryTitulos.State in dsEditModes);
spbSalvar.Visible
:= (DM.qryTitulos.State in dsEditModes);
end;

Listagem 3. Ativa e Desativa botes


Muito bom, agora precisamos apenas fazer as devidas chamadas ao mtodo AtualizarBotoes. A princpio podemos
colocar nos eventos OnCreate do formulrio de Ttulos e tambm no OnItemClick do ListView de listagem de ttulos,
assim quando o usurio tocar em um ttulo para ver os detalhes, os botes ficaro disponveis para a edio. No evento
OnClick de cada boto novo teremos que codificar para fazer a edio do registro selecionado. O cdigo bem simples.
Veja a Listagem4 com toda a seqncia de cdigo de cada boto.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

procedure TfrmTitulos.spbCancelarClick(Sender: TObject);


begin
DM.qryTitulos.Cancel;
AtualizarBotoes;
end;
procedure TfrmTitulos.spbEdicaoClick(Sender: TObject);
begin
DM.qryTitulos.Edit;
AtualizarBotoes;
end;
procedure TfrmTitulos.spbSalvarClick(Sender: TObject);
begin
DM.qryTitulos.Post;
AtualizarBotoes;
end;

Listagem 4. Cdigo dos botes de edio


Para quem mais experiente, esse cdigo realmente simples ao extremo. Claro que poderamos fazer uma srie
de checks para evitar que o usurio deixe de preencher um determinado campo, tratamentos de erro, etc. Mas por
enquanto faremos o mais grosso da programao. Com isso codificado, j podemos testar nossa aplicao.
Ao tocar no boto Editar, os botes Salvar e Cancelar devem aparecer e o botes Editar e Voltar devem sumir, assim o
usurio somente poder Salvar ou Cancelar a ao.
Para tirarmos uma foto ou escolhermos da biblioteca, usaremos aes do TActionList. Por isso adicione ao formulrio
um TActionList, d o nome de AcoesGeral e clique duas vezes nele. Na janelinha que se abre clique na setinha preta
que aparece ao lado boto de criao de novas aes (Figura 3 e 4).

Figura 3. Criando nova ao

__________________________________________________________________________________________
37

Figura 4. Criando nova ao

Fiz o print das telas propositadamente com o cursor selecionado na opo Media Library. Essas so aes prontas do
Delphi. Na seqncia vemos:
TTakePhotoFromLibraryAction
TTakePhotoFromCameraAction
TShowShareSheetAction
As duas primeiras so usadas respectivamente para selecionar uma foto da Galeria (Android) ou Biblioteca (iOS) e a
segunda usada para tirar uma novo nova. A terceira opo usada para invocar a tela de compartilhamento nas
redes sociais, etc.
Adicione uma ao para Cmera e outra para Biblioteca. Chame-as de actFotoCamera e actFotoBiblioteca. Depois de
criadas ns podemos clicar na ao e acessar suas propriedades e eventos. O que precisamos aqui s do evento
OnDidFinishTaking, que ser codificado por ns. Clique duas vezes nesse evento para a ao actFotoCamera.
Esse evento ocorre logo depois da captura da foto, ou seja, aps o usurio tirar a foto e escolher usa-la. Ns
carregaremos a foto diretamente para o campo FOTO em nosso banco de dados. Para isso apenas digite no evento:
?

DM.qryTitulosFOTO.Assign(Image);

O parmetro Image vem do prprio evento e carregado automaticamente pelo Delphi aps a captura de foto. Essa
mesma linha pode ser digitada no mesmo evento para a segunda ao, faa isso.
Se voc escreveu os cdigo corretamente para cada boto como indicado mais acima, ento at aqui no teremos
problemas e tudo estar funcionando perfeitamente.
Retornaremos em breve aqui, pois teremos que codificar o momento certo de chamar esses mtodos.

Gerando um novo registro


No incio no post mencionei que iramos montar uma funo para gerar automaticamente nossos IDs, e isso que
faremos agora. Algo relativamente simples e que nos ajudar com o reaproveitamento de cdigo. Acesse nosso
DataModule e crie uma nova function na seo Public no formulrio.
?
1

function GetIDFromTable(ATable: String) : Integer;

Pressione Ctrl + Shift + C para que o Delphi crie o escopo no mtodo e ento digite o cdigo da Listagem 5. Perceba
que criamos uma constante chamada _SQL que recebe SELECT MAX(ROWID)+1 AS NEW_ID FROM %s. Isso bem
simples.

__________________________________________________________________________________________
38

RowID um campo oculto nas tabelas do SQLite que bastante comum em alguns bancos de dados, tal como Oracle.
Ele uma espcie de controle interno do banco de dados. O que faremos igualar o campo ID_TITULO de nossa tabela
ao valor desse campo. Usamos Max para pegar o maior valor nesse campo e adicionamos +1. O %s um coringa que
usaremos para substitui-lo pelo nome da tabela, ou seja, teremos uma instruo SQL assim:
?
1

SELECT MAX(ROWID)+1 AS NEW_ID FROM TITULOS

Resultaremos o valor do campo NEW_ID.


?
1
2
3
4
5
6
7
8
9
10
11

function TDM.GetIDFromTable(ATable: String): Integer;


const
_SQL = 'SELECT MAX(ROWID)+1 AS NEW_ID FROM %s';
begin
with qryAuxiliar1 do
begin
Active := False;
SQL.Clear;
SQL.Text := Format(_SQL, [ATable]);
Active := True;
Result := FieldByName('NEW_ID').AsInteger;
end;
end;

Listagem 5. Gerando ID da tabela


Tambm peo que altera a instruo SQL da query qryTitulos incluindo o campo ROWID no incio da select e tambm
incluindo seu campo no Fields Editor. Consulte a parte II desse tutorial para ver como faz caso tenha dificuldades. Por
fim adicione um novo componente query a tela chamando-o de qryAuxiliar1. Todas instrues SQL que precisarmos
fazer e que sejam temporrias, usaremos esse componente.
Agora retorne ao frmTitulos e acessa a primeira aba, a de listagem dos Ttulos. Crie um novo speedbutton na tela
dentro de nossa barra de ferramentas superior. Alinhe esse boto a direita com Margem Direita igual a 8px. Selecione
o StyleLoookup addtoolbutton para termos um boto de adio de novo ttulo.
Esse boto dever fazer algo bem simples.
Chamar o mtodo de atualizao dos botes em tela;
Adicionar um novo registro a tabela Ttulos;
Chamar a Aba de Detalhes.
A aba de detalhes dever receber uma alterao grande agora, pois no temos onde digitar os valores Ttulo, SubTtulo
e Ano de Lanamento, pois colocamos apenas Labels nessa tela. Portanto faremos a troca desses labels por Edits.
Troque os trs labels por edits, na seqncia: edtTitulo, edtSubTitulo e edtAnoLancamento. Refaa o Binding, voc
ligar novamente cada campo da tabela aos respectivos edits. Voc j sabe fazer isso, basta consultar os demais
tutoriais ou o vdeo sobre Binding disponvel em nosso YouTube.
Veja como deve ficar seu Layout nas Figuras 5, 6 e 7.

Figura 5. Exemplo de Tela

__________________________________________________________________________________________
39

Figura 6. Exemplo de Tela

Figura 7. Exemplo de Tela


A mgica simples. Quando entrarmos em modo de Edio ou Insero, mudaremos a propriedade Enabled de cada
controle para aceitar nossas digitao. Quando estiver em modo Browse, ou seja, apenas visualizao, os edits ficaram
desativados. Mas alm disso mudaremos tambm o StyleLookup de cada controle para que fiquem transparentes,
dando a impresso de Labels.
Retorne a nossa funo AtualizarBotoes e acrescente o cdigo da Listagem 6.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

edtTitulo.Enabled
:= (DM.qryTitulos.State in dsEditModes);
edtSubTitulo.Enabled := (DM.qryTitulos.State in dsEditModes);
edtAno.Enabled
:= (DM.qryTitulos.State in dsEditModes);
if (DM.qryTitulos.State in
begin
edtTitulo.StyleLookup
edtSubTitulo.StyleLookup
edtAno.StyleLookup
end
else
begin
edtTitulo.StyleLookup
edtSubTitulo.StyleLookup
edtAno.StyleLookup
end;

dsEditModes) then
:= 'editstyle';
:= 'editstyle';
:= 'editstyle';

:= 'transparentedit';
:= 'transparentedit';
:= 'transparentedit';

Listagem 6. Complemento do cdigo


Repare que igualamos a propriedade Enabled ao estado da tabela. E ainda modificamos o StyleLookup dos
componentes. Pronto, precisamos apenas fazer a chamada do cdigo para incluso de ttulos.
Retorne a aba principal e clique duas vezes em nosso boto +. Digite o cdigo a seguir:
?

__________________________________________________________________________________________
40

1
2
3

DM.qryTitulos.Append;
tabctrlTitulos.Next;
AtualizarBotoes;

No d para ser mais simples que isso. Append para criar um novo registro, mudamos para a aba de detalhes e
atualizamos os botes que consequentemente tambm ativar os edits para incluso de dados.

Criando um pop-up menu

Ns preparamos nosso cdigo para ativarmos a cmera ou a biblioteca de fotos, mas no fizemos as devidas chamadas
ainda. Faremos o seguinte: quando o usurio tocar na foto na tela de detalhes, ento acionaremos um pop-up menu e
perguntaremos o que o usurio deseja fazer:
Nova Foto;
Biblioteca
Cancelar
Desse modo, cada item do pop-up chamar uma determinada ao. Para fazer esse menu usaremos um artifcio bem
comum, um ListBox. Isso mesmo! Insira um ListBox na tela e clique duas vezes nele para adicionar itens. Crie trs itens
e altere suas propriedades como a seguir:
Name: lstitNovaFoto
Text: Nova Foto
Name: lstitBiblioteca
Text: Biblioteca
Name: lstCancelar
Text: Cancelar
Eu modifiquei as fontes de cada item do listbox, mas fica a seu critrio. Tambm importante modificar a altura de
todos os itens, use a propriedade ItemHeight do prprio ListBox e altere-a para 40 que um bom nmero. A aparncia
desse listbox deve ser parecida como a Figura 8.

Figura 8. Popup menu


Arraste esse ListBox para o Layout do frmTitulos. Ele deve ficar como na Figura 9.

Figura 9. Estrutura de componentes.


Para que ele fique com uma sombra em volta, localize o componente TShadowEffect e arraste-o para o listbox, como
na Figura 10.

Figura 10. Sombra

__________________________________________________________________________________________
41

Perfeito! Agora temos que preparar a logstica para que tudo isso funcione. Ns faremos o menu aparecer de cima
para baixo com uma animao, e desaparecer do mesmo modo. Para que possamos sumir com o menu quando o
usurio tocar fora, usaremos nossa antiga tcnica de criar um retngulo escuro por baixo de tudo. Ns vimos isso no
primeiro tutorial. Voltaremos com a ideia.
V at o formulrio principal, frmMain, e adicione um TRectangle de qualquer tamanho e modifique sua propriedade
Opacity para 0.5. Na seo Public do form, crie dois mtodos:
?
1
2

procedure ShowBackground(AParent: TFmxObject; AOnClick: TNotifyEvent = nil);


procedure HideBackground;

E codifique-os como na Listagem 7.


?
1
2
3
4
5
6
7
8
9
10
11
12
13

procedure TfrmMain.HideBackground;
begin
recBackground.AnimateFloat('opacity', 0, 0.1);
recBackground.Visible := False;
end;
procedure TfrmMain.ShowBackground(AParent: TFmxObject; AOnClick: TNotifyEvent);
begin
recBackground.OnClick := AOnClick;
recBackground.Parent := AParent;
recBackground.BringToFront;
recBackground.Opacity := 0;
recBackground.Visible := True;
recBackground.AnimateFloat('opacity', 0.5, 0.1);
end;

Listagem 7 Background em principal


O procedimento exatamente igual ao que fizemos na primeira parte do tutorial, portanto no explicarei novamente.
Apenas para entendermos, ns chamaremos ShowBackground sempre que precisarmos mostrar o fundo escuro e
HideBackground para sumir como ele.
J na tela frmTitulos ns criaremos um mtodo para sumir com o pop-up, ento crie um novo mtodo com o nome
HidePopup e digite o cdigo a seguir:
?
1
2
3

frmMain.HideBackground;
lstPopUpFoto.AnimateFloat('position.y', lstPopUpFoto.Height * -1);
lstPopUpFoto.Visible := False;

Simples no? Chamamos o mtodo HideBackground presente no formulrio principal e depois as animaes para
esconder o menu. Por default o menu deve ficar invisvel e longe do alcance dos olhos, portanto no OnCreate do
formulrio de ttulos adicione o cdigo da Listagem 8.
?
1
2
3
4
5
6

lstPopUpFoto.Width
lstPopUpFoto.Position.X
lstPopUpFoto.Position.Y
lstPopUpFoto.Visible

:=
:=
:=
:=

ClientWidth - 20;
(ClientWidth - lstPopUpFoto.Width) / 2;
lstPopUpFoto.Height * -1;
False;

AtualizarBotoes;

Listagem 8. OnCraete do formulrio


O que estamos fazendo no mtodo , em resumo, aumentar sua largura automaticamente para que fique com um
tamanho mais adequado a largura do device e depois posicionamos ele acima da barra de ttulo do aparelho e
deixando-o invisvel.
Acesse agora a aba detalhes e clique duas vezes no nosso imgFoto para adicionar um novo cdigo ao evento OnClick
do objeto. Ns chamaremos agora o menu pop-up. Digite o cdigo da Listagem 9.
?
1
2
3
4
5
6
7
8

procedure TfrmTitulos.imgFotoClick(Sender: TObject);


begin
if DM.qryTitulos.State in dsEditModes then
begin
frmMain.ShowBackground(Self.lytTitulos, lstitCancelarClick);
lstPopUpFoto.Visible := True;
lstPopUpFoto.AnimateFloat('position.y', 0);
lstPopUpFoto.BringToFront;

__________________________________________________________________________________________
42

9
10

end;
end;

Listagem 9. Chamada para o popup


Na Listagem 9 fazemos primeiro uma checarem para ver se o usurio colocou o registro em alterao, evitando um
erro na tela. Em seguida mostramos o fundo escuro e descemos o popup usando o mtodo AnimateFloat passando a
nova posio vertical dele, position.y.
Feito. Somente precisamos agora codificar a ao de cada item do ListBox. No OnClick do primeiro item digite:
?
1
2

HidePopup;
actFotoCamera.ExecuteTarget(Sender);

No segundo repita e mude apenas a chamada para a biblioteca.


?
1
2

HidePopup;
actBiblioteca.ExecuteTarget(Sender);

E caso o usurio queira desistir de tirar foto, apenas chame HidePopup e HideBackground para sumir com o popup de
tela.
?
1
2

HidePopup;
frmMain.HideBackground;

Excluindo registros
Para fecharmos com chave de ouro, precisaremos fazer a excluso de registros e o PullToRefresh, ou seja, puxe para
atualizar. Usaremos gestos para isso, mas os defaults. Quando o usurio arrastar o dedo para os lados, um boto Delete
dever aparecer. Se puxar de cima para baixo, ento atualizamos a tabela. Isso tudo no ListView.
Bem, o PullToRefresh j est pronto. Apenas ative a propriedade PullToRefresh e ento codifique o evento
OnPullToRefresh. Digite apenas:
?
1
2

DM.qryTitulos.Active := False;
DM.qryTitulos.Active := True;

Ou seja, apenas fechamos e abrimos a query.


Para excluir basta ativar a propriedade CanSwipeDelete e codificar o evento OnDeletingItem. Nesse caso vamos a
explicao.
Esse evento ocorre no momento que o usurio clica no boto para excluso do item e o mesmo entra em modo de
excluso definitiva. Ns temos uma varivel nesse evento chamada ACanDelete. Se no codificarmos nada nesse
evento, o item ser apagado do ListView, mas no do banco de dados, o que acabar voltando se o usurio der um
PullToRefresh ou fechar e reabrir o app. Por isso excluiremos tambm do banco.
Levando em considerao que no sabemos exatamente qual ID do Ttulo estamos excluindo, usaremos o INDEX da
linha excluda como base. Sabemos que o ListView inicia sua contagem em 0 (zero), somaremos +1 para obtermos o
ROWID exato do registro a ser excludo do banco. Portanto faremos um Locate na tabela para pararmos em cima do
registro e apagaremos. Digite ento o cdigo da Listagem 10.
?
1
2
3
4
5
6
7
8
9
10

procedure TfrmTitulos.lsvTitulosDeletingItem(Sender: TObject; AIndex: Integer;


var ACanDelete: Boolean);
begin
ACanDelete := MessageDlg('Confirma excluso de ttulo?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0 ) = mrYes;
if ACanDelete then
begin
DM.qryTitulos.Locate('ID_TITULO', AIndex+1, []);
DM.qryTitulos.Delete;
end;
end;

Listagem 10. Excluso


Perceba. Perguntamos ao usurio se ele deseja excluir o registro e igualamos o seu resultado a varivel ACanDelete.
Caso ela receba True, ou seja, SIM, ento localizamos o registro e exclumos.
__________________________________________________________________________________________
43

Como isso encerramos a quarta parte de nosso tutorial. Ainda ser disponibilizado um vdeo com mais alguns detalhes.
Ento fiquem de olho, pois esse post sofrer algumas modificaes.

Concluso
Nesse tutorial vimos muitas das operaes triviais de qualquer aplicativo. Mas tambm vimos tcnicas simples, porm
eficazes para criar um pop-up de menu, muito utilizado em aplicaes mveis. Vimos tambm a utilizao de aes
padres e o uso de contedo do aparelho, como fotos.

__________________________________________________________________________________________
44

Criando meu app step-by-step Estilo Parte V

Bem vindos a parte V de nosso Tutorial: Criando meu app step-by-step a partir do desenvolvimento em RAD Studio XE7.
At agora entendemos uma srie de mecanismos que nos ajuda a desenvolver de forma mais rpida e intuitiva, criando
nossas telas, capturando fotos, ligando controles a campos do banco de dados, etc.
Relembrando da seo passada, ns vimos:
Criao de campo do tipo imagem na tabela de Ttulos;
Criao de mtodo para auto-numerar ID de Ttulos;
Binding da imagem com as listagem e detalhes do Ttulo;
Incluso, Alterao e Excluso de Ttulos;
Seleo de fotos da biblioteca ou cmera;
Essa seo ser um pouco mais light. Entenderemos como aplicar um estilo mais profissional ao aplicativo, instalao
e configurao do cliente Git para clone de nosso fonte do Bitbucket. E tambm criaremos uma janela de configurao
para guardar preferncias do usurio. Segue a lista:
Instalao e configurao do Git no Delphi XE7;
Como aplicar estilos mais profissionais?
Criando uma janela de preferncias;
Criao de classe para guardar informaes de preferncias.

Requisitos:
Leitura: Tutorial: Criando meu app step-by-step parte IV;

1.
2.
3.
4.
5.

Usando um estilo mais profissional


A primeira coisa que aprenderemos nesse passo do tutorial, adicionar um novo estilo ao nosso app. Isso possvel
por conta do Firemonkey. Para quem novato em Delphi XE, o Firemonkey um framework poderoso criado
pela Embarcadero que possui uma infinidade de recursos, e culpa dele que hoje temos a possibilidade de
desenvolver apps para n plataformas. Sem contar, claro, com o novo compilador ARM que d vida a tudo.
Em funo disso, podemos criar, editar e adicionar novos estilos aos nossos apps tanto para
plataforma Mobile quanto Desktop, tais como Mac e Windows. A Embarcadero disponibiliza um pacote de estilos
prontos para usurios registrados. Basta acessar o site http://cc.embarcadero.com/item/29928 e baixar o pacote
completo. Nesse caso usaremos o pacote Premium Style Pack for RAD Studio XE7.
Com o pacote aberto e descompactado ns vamos aprender a instalar o tema nas pastas do XE7. Abra o Windows
Explorer em seu computador e abra a pasta referente ao pacote descompactado. Perceba que temos uma pasta para
cada plataforma conforme a Figura 1.

Figura 1. Tema descompactado

__________________________________________________________________________________________
45

Eu costumo copiar os estilos na pasta de Styles do Delphi, mas na verdade voc pode colar onde voc desejar. Nesse
artigo
veremos
onde
podemos
instalar
tais
temas.
Acesse
a
pasta C:\Users\Public\Documents\Embarcadero\Studio\15.0\Styles. Nessa pasta voc tambm encontra os arquivos
separados por plataforma, ento agora fica fcil. Basta deixar dois explorers lado a lado e copiar e colar cada tema em
sua respectiva pasta.
Agora que temos os temas devidamente instalados, basta que faamos a adio no nosso projeto. Para isso abra o
Delphi XE7 e em seguida nosso projeto. No form principal, frmMain, adicione um componente do
tipo TStyleBook. Localize-o digitando seu nome da caixa de pesquisa na paleta de componentes.
Agora selecione a plataforma Android sua direita no Project Manager. Isso necessrio pois voc pode adicionar um
estilo para cada plataforma se desejar. Selecionada a plataforma, clique duas vezes no componente StyleBook1 criado
anteriormente. Voc ver alguns botes na parte superior, um deles o Load, para carregarmos o estilo que
desejamos. Clique nesse boto e localize o arquivo AndroidEmeraldDark.style naquela mesma pasta onde colocamos
os temas. Em seguida clique em Apply & Close. Selecione agora o formulrio em si e em sua
propriedade StyleBook selecione o componente de mesmo nome, isso far com que o tema seja aplicado
imediatamente, como podemos ver na Figura 2.

Estilo aplicado ao formulrio


Figura 2. Tema aplicado
Se voc desejar aprender mais sobre o esquema de estilos, basta ler ao artigo o artigo na docwiki nesse link.

Criando um arquivo de configuraes


A grande maioria dos aplicativos que usamos no dia-a-dia possuem configuraes de usurio, preferncias. Em nosso
app no ser diferente. Aprenderemos agora a criar uma janela com preferncias do usurio utilizando um arquivo do
tipo INI (Inicializao). Isso mesmo! Da mesma forma que fazemos em Windows.
Vamos primeiro alterar nossa interface. Crie um novo item no nosso ListBox de menu. Esse item dever se
chamar lstPreferencias e ter seu Text alterado para Preferncias, sem spas claro.
Em seguida crie um novo formulrio assim como fizemos nas aulas anteriores. No esquea de incluir uma ToolBar na
parte superior com um SpeedButton chamado spbBack para que possamos ter um boto para abrir o menu principal
quando desejarmos. D o nome a esse formulrio de frmPreferencias e salve a a unit como UntPreferencias.pas.

Adicione um novo boto alinhado direita com margem direita de 8px. O seu Text dever ser Gravar e o
name spbGravar. Esse boto ser nosso boto para gravao das preferncias em arquivo INI. A tela dever se parecer
com a Figura 3.

__________________________________________________________________________________________
46

Figura 3. Sugesto de tela de configuraes


Assim como nas telas de Ttulos e Login, inserimos um TLayout no fundo e dentro dele inserimos o demais
componentes. Nesse caso inseri um ListBox no formulrio alinhado como Client. Fixei a altura das linhas em 44 usando
a propriedade ItemHeight e em seguida adicionei um novo item. Para isso, clique duas vezes no ListBox. Isso far com
que se abra a janela de gerenciamento dos itens do ListBox. No ComboBox direita selecione a
opo TListBoxGroupItem como na imagem a seguir:

Adicione um Item de cabealho e em seguida um item comum. O primeiro deles d o nome de lstgrpSeguranca e
seu Text mude para Segurana. Em seguida modifique o name do segundo item para lstitDesconectar e seu Text para
Desconectar ao sair. Adicione dentro desse item de ListBox um componente TSwitch e d o nome a ele
de swtDesconectar. Alinhe-o a direita com margem direita igual a 8px.

Codificando o arquivo INI


Muito bom at aqui. Com nossa interface pronta, vamos preparar as funes de gravao e leitura do arquivo INI. Para
facilitar todo o trabalho, vamos criar uma classe para ler e escrever no arquivo INI, bem como alimentar as propriedades
do menu principal. Propriedades? Sim, vamos comear a brincar um pouco com orientao a objetos.
Crie uma nova unit em File > New > Unit. Salve-a como ULib.pas. De preferncia crie uma pasta no projeto
chamada Lib e salve essa Unit l dentro, assim deixamos tudo mais organizado.
Com a unit aberta, adicione uma clusula Uses abaixo de Interface e declare as Units IniFiles e System.IOUtils, como
mostrado abaixo:
?
1
2
3

interface
uses
IniFiles, System.IOUtils

Em seguida escreva o cabealho das funes e propriedades que vamos codificar aqui. Veja a Listagem 1 como o cdigo
precisa ser implementado.
?
1
2
3

type
Lib = class
private

__________________________________________________________________________________________
47

4
5
6
7
8
9
10
11
12
13

FDesconectarAoSair: Boolean;
function GetDesconectarAoSair: Boolean;
procedure SetDesconectarAoSair(const Value: Boolean);

public
procedure SaveConfig;
procedure ReadConfig;
published
property DesconectarAoSair: Boolean read GetDesconectarAoSair write SetDesconectarAoSa
end;

Listagem 1. Cdigo do cabealho dos mtodos

Ns criamos uma propriedade chamada DesconectarAoSair do tipo Boolean (True/False) e guardarmos a informao
se o usurio deseja ou no sair totalmente do sistema ao sair do aplicativo. Em seguida criamos dois mtodos:
SaveConfig: Salvar os dados no arquivo INI;
ReadConfig: Ler dados do arquivo INI;
Pressione Ctrl +Shift + C para que o Delphi crie para ns o escopo dos mtodos. Ns faremos algo bem simples j que
temos apenas uma configurao para ser guardada no arquivo INI. Digite o cdigo da Listagem 2.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

function Lib.GetDesconectarAoSair: Boolean;


begin
Result := FDesconectarAoSair;
end;
procedure Lib.ReadConfig;
var
Ini : TIniFile;
begin
try
Ini := TIniFile.Create(TPath.Combine(TPath.GetDocumentsPath, 'Config.ini'));
FDesconectarAoSair := Ini.ReadBool('SEGURANCA', 'DesconectarAoSair', FDesconectarAoSair);

finally
Ini.DisposeOf;
end;
end;
procedure Lib.SaveConfig;
var
Ini : TIniFile;
begin
try
Ini := TIniFile.Create(TPath.Combine(TPath.GetDocumentsPath, 'Config.ini'));
Ini.WriteBool('SEGURANCA', 'DesconectarAoSair', FDesconectarAoSair);
finally
Ini.DisposeOf;
end;
end;
procedure Lib.SetDesconectarAoSair(const Value: Boolean);
begin
FDesconectarAoSair := Value;
end;

Listagem 2. Escopo dos mtodos


Em SaveConfig e ReadConfig ns declaramos uma varivel do tipo TIniFile. Criamos o arquivo INI usando o
mtodo Create da classe TIniFile e ento recebemos ou gravamos o valor encontrado, direto na
varivel FDesconectarAoSair, que a varivel referente a nossa propriedade de mesmo nome.
Antes de prosseguirmos com a codificao em frmPreferencias, necessitamos fazer algumas alteraes no frmMain,
ou seja, no formulrio principal. Retorne a ele e logo de incio faa um File > Use Unit e adicione a ULib na
seo Interface do formulrio principal. Aproveite e adicione tambm a unit UntPreferencias.
Na seo public do formulrio, adicione uma nova varivel para fazermos referncia ao formulrio de preferncias.
Chame-a de FPreferencias do tipo TfrmPreferencias.
Agora crie uma varivel chamada FLib do tipo TLib. Essa varivel ser usada para instanciarmos a classe TLib e usarmos
sempre que precisarmos. Nossas declaraes devem ficar como na codificao abaixo:

__________________________________________________________________________________________
48

?
1
2
3
4
5
6
7
8
9

[...]
uses
ULib,
UntPreferencias;
[...]
public
FPreferencias : TfrmPreferencias;
FLib
: TLib;
[...]

Acesse o evento OnCreate do form principal e faa a criao da instncia de FLib, como abaixo:
?
1
2

FLib := TLib.Create;
FLib.ReadConfig;

J no evento OnClose, precisamos dispensar a varivel para evitar MemoryLeak. Faa como abaixo:
?
1
2

if Assigned(FLib) then
FLib.DisposeOf;

Agora falta apenas, nesse formulrio, fazer a chamada para o form de preferncias. Clique duas vezes no item de
listbox referente ao menu preferncias e codifique-o como na Listagem 3.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

procedure TfrmMain.lstPreferenciasClick(Sender: TObject);


begin
if not Assigned(FPreferencias) then
FPreferencias := TfrmPreferencias.Create(Self);
MultiView1.MasterButton := FPreferencias.spbBack;
MultiView1.HideMaster;
{Adiciona o Layout de Pedidos ao Layout Principal que controla tudo}
lytMain.AddObject(FPreferencias.lytPreferencias);
try
DM.qryTitulos.Active := False;
DM.qryTitulos.Active := True;
except on E:Exception do
ShowMessage('Click em Ttulos: ' + E.Message);
end;
{Deixa todos os layouts invisveis e deixa o layout alvo visvel}
ShowForm(FPreferencias.lytPreferencias);
end;

Listagem 3. Chamada para o form de preferncias


Para finalizar essa parte, precisamos acessar o evento OnCreate do formulrio preferncias e fazer a chamada a
nossa Lib para que possamos atualizar os controles em tela de acordo com o que est gravado no arquivo INI, bem
como gravar as novas alteraes.

Cadastro de Preferncias
Como nossa janela de preferncias s possui um item para ser gravado, ento vai ser fcil codificarmos. Precisamos
gravar o que o usurio escolheu e na abertura da tela precisamos ler o que foi gravado e atualizar a tela. Publiquei
na Listagem 4 o cdigo completo dos dois eventos, OnCreate e OnClick (spbGravar).
?
1
2
3
4
5
6
7
8
9
10
11

procedure TfrmPreferencias.FormCreate(Sender: TObject);


begin
frmMain.FLib.ReadConfig;
swtDesconectar.IsChecked := frmMain.FLib.DesconectarAoSair;
end;
procedure TfrmPreferencias.spbGravarClick(Sender: TObject);
begin
frmMain.FLib.DesconectarAoSair := swtDesconectar.IsChecked;
frmMain.FLib.SaveConfig;
end;

__________________________________________________________________________________________
49

Listagem 4. Cdigos do OnCreate e OnClick


Note que fazemos referncia ao formulrio principal, frmMain, por isso necessrio fazer um Use Unit nele. Fazemos
isso porque estamos lendo as propriedades da classe TLib atravs da varivel FLib no form principal. No
evento OnCreate ns lemos as informaes e atualizamos o controle swtDesconectar. Estamos igualando sua
propriedade IsChecked ao valor boleano gravado no arquivo INI.
Do mesmo modo, evidentemente ao contrrio, gravamos o estamos do controle swtDesconectar no arquivo INI,
fazemos essas duas operaes chamando os mtodos ReadConfig e SaveConfig respectivamente.

Configurando e baixo um cdigo-fonte usando Git no RAD Studio XE7


Para aqueles que no sabem ainda, o RAD Studio XE7 implementou suporte ao GIT. O Git uma, grosseiramente
falando, plataforma de gerenciamento e cdigo-fonte. Com ele conseguimos fazer commits, controles de cdigo-fonte,
controle de diferenas, e uma srie de outras funcionalidades esto disponveis nele. Atualmente o Git bastante
utilizado assim como SVN, j existente no Delphi h tempos.
Nessa seo aprenderemos a configurar o Git no Delphi e baixar o cdigo-fonte desse tutorial diretamente pelo Delphi.
A primeira providncia instalar o cliente do Git em seu Windows/Mac. Para isso acesse o link http://www.gitscm.com/download e baixe a verso que melhor se encaixe com seu perfil. Nesse tutorial mostrarei somente o uso
com Windows.
Feito o download do arquivo (at o fechamento desse artigo) Git-1.9.4-preview20140929.exe, clique duas vezes nele e
clique logo de incio em Next em todas as janelas. Deixei propositalmente default em todos os passos. Aguarde a
instalao e ento voltemos at o Delphi.
Com o Delphi aberto, precisaremos indicar a ele onde o arquivo principal do Git est instalado. Para isso acesse Tools
> Options > Version Control > Git. Em Git Executable clique no boto reticncias direita e navegue at a pasta de
instalao do Git, normalmente em C:\Program Files (x86)\Git\bin\git.exe.
Feito isso estamos prontos para fazer o download de nosso cdigo-fonte. Acesse o menu File > Open from source
control e em seguida selecione Git. Na janela seguinte cole o endereo completo de nosso fonte no Bitbucket. Caso
no saiba, acesse https://bitbucket.org/tdevrocks e selecione o nosso curso. direita do site voc encontrar o
caminho completo para o site.
O segundo campo dessa caixa de dilogo o local onde o cdigo-fonte dever ser baixado. Fica a seu critrio nesse
caso. Veja todos esses passos nas imagens abaixo:

Abertura do arquivo fonte

Seleo do Git

Endereo remoto e local do repositrio

__________________________________________________________________________________________
50

Endereo remoto

Download

Finalizao

Quando o download finalizar, o Delphi detectar se h algum arquivo .dpr, .dproj e etc e j far a sugesto de abertura
do arquivo. Voc pode cancelar nesse momento se desejar.
O cdigo-fonte desse exemplo encontra-se disponvel aqui.

Concluses
Nesse artigo pudemos aprender como fcil adicionar um novo estilo as nossas aplicaes Delphi para Mobile, bem
como para desktop Windows e Mac. O aprendizado aqui serve no somente para aplicativos multi-device, mas caso
voc deseje adicionar um estilo profissional a sua aplicao, os passos tambm so vlidos.
Tambm aprendemos a usar arquivos INI para ler e gravar informaes nos diretrios do dispositivo mvel. Por fim,
aprendemos a configurar o Git para efetuar o clone de nosso projeto no Bitbucket. Os passos vistos aqui, tambm so
vlidos para qualquer outro cdigo-fonte disponvel na nuvem ou localmente.

__________________________________________________________________________________________
51

Criando meu app step-by-step DataSnap REST Parte VI

Criando meu app step-by-step tem se tornado uma referncia a muitos seguidores do blog, e ns agradecemos muito
;). Mas at o presente momento, estamos vendo coisas bsicas no Delphi ento hora de avanarmos um pouco mais.
Nessa sexta parte, iniciaremos a criao de um servidor de aplicativos desenvolvido com DataSnap REST, passando pelo
conceito de Reflection no FireDAC no futuro, bem como o uso de objetos JSON para troca de DataSets entre cliente e
servidor. Calma, calma! Para os iniciantes, tanto no Delphiquanto no DataSnap, isso pode parecer uma Hidra de Lerna,
vulgarmente chamada de Bicho de Sete Cabeas. Mas no, ser fcil.
No artigo anterior, ns aprendemos a criar uma janela de configuraes utilizando arquivos INI para persistir as
preferncias do usurio, alm de outras coisas. Confira:
Instalao e configurao do Git no Delphi XE7;
Como aplicar estilos mais profissionais?
Criando uma janela de preferncias;
Criao de classe para guardar informaes de preferncias.
Nesta sexta parte, veremos como criar nosso servidor DataSnap e como configurar nossa aplicao cliente para ler
nossos ServerMethods.
Criao do servidor DataSnap;
Criao do mdulo de conexo com o servidor DataSnap;
Teste de conexo.

Requisitos:
Leitura: Leitura do artigo Parte V;
Vdeo: Assistir ao vdeo complementar em nosso canal no YouTube;

Criando o servidor DataSnap REST


Antes de iniciarmos a criao de nosso servidor, precisamos entender exatamente o que faremos aqui. Atualmente
temos somente uma tabela em nosso banco de dados local, TITULOS, que armazena os DVDs que podemos alugar em
nossa locadora. Possibilitamos o usurio final (administrador) fazer a incluso, excluso e alterao de titulos. Mas isso
hoje fica somente no dispositivo mvel, o que ruim. Nossa ideia inicial era que o aplicativo fosse apenas um sistema
para uso do administrador da locadora, que poderia alugar, devolver ou ainda conferir quais itens esto emprestados.
A ideia agora fazer com que possamos atualizar nosso servidor central com informaes do que foi efetuado no
mobile, bem como atualizar o mobile com informaes dos ttulos que esto no servidor central. Faremos isso
com DataSnap.
No esquema da Figura 1, vemos como funcionar nosso sistema.

Figura 1. Esquema DataSnap


Note que nossa arquitetura prev que nossos aplicativos mveis utilizaro internet para chegar ao servidor e
consequentemente, chegar ao banco de dados.

__________________________________________________________________________________________
52

Criando o servidor
Com o RAD Studio XE7 aberto e nosso projeto tambm j aberto na IDE, vamos adicionar um novo projeto clicando
com o boto direito em ProjectGroup1 no Project Manager a nossa direita (Figura 2). Selecione Add New Project.

Figura 2. Criao do Projeto


Isso far com que a janela de criao de novos projetos seja aberta pelo Delphi. Voc precisar clicar em Delphi Projects
> DataSnap Server e use o item DataSnap REST Application. Em seguida marque a opo Stand-alone
application e Next. Aceite a opo default, VCL application e novamente em Next. A tela seguinte nos d como
sugesto a porta 8080. Essa ser a porta que nosso aplicativo mvel (ou desktop) usar para se conectar com o servidor.
Vamos usar essa porta mesmo, mas lembre-se se seu Windows precisar ter essa porta liberada no Firewall.
Passe a tela seguinte sem selecionar nenhuma opo adicional e em seguida use TDataMobule como classe para
nossos ServerMethods.Isso far com que o Delphi crie para ns um DataModule onde colocaremos nossos
componentes de acesso a dados. Por fim selecione um caminho para salvar o cdigo-fonte do servidor e clique
em Finish. Como sugesto, criei uma pasta chamada DataSnapServer na raiz de nosso curso.

Entendendo o Servidor

Depois de clicar em Finish, o Delphi cria para ns todos os arquivos necessrios e as respectivas configuraes para
que o servidor funcione corretamente em modo Stand-alone, ou seja, em modo executvel. Voc perceber que temos
trs arquivos abertos:
FormUnit1: Formulrio principal do servidor;
ServerMethodsUnit1: Servidor de Mtodos;
WebMobuleUnit1: Principal unit do servidor, possui os componentes que mantm o servidor no ar, tal como DSServer.
O primeiro formulrio da lista, salve-o como UntMainServer.pas e d o nome (Propriedade Name) a ele
de frmMainServer. Em seguida salve o segundo formulrio como UntServerMetodos.pas e d o Name
de SrvServerMetodos. Por fim salve o WebModuleUnit1 como UntWebModulo.pas e troque seu Name
para webModulo.
Aproveitando que estamos no webModulo, vamos analisar esse formulrio. O primeiro componente importante desse
formulrio o DSServer1. ele que recebe todas as requisies de aplicaes cliente, sejam elas mobile, sejam elas
desktop Windows ou Mac.
Em seguida ns temos um DSServerClass1. Esse componente responsvel por exportar as classe e consequentemente
os mtodos do servidor para o cliente. Podemos ter quantos componentes desse quisermos. Clique nesse componente
e acesse seu evento OnGetClass.Teremos seguinte cdigo:
?
1
2
3
4
5

procedure TwebModulo.DSServerClass1GetClass(
DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
PersistentClass := UntServerMetodos.TSrvServerMetodos;
end;

__________________________________________________________________________________________
53

Para sermos bem simplistas, estamos exportando a Unit ServerMetodos inteira para o cliente, o que significa que tudo
que estiver programado l dentro, ser exportado e poder ser acessado, como por exemplo nossos mtodos de acesso
a banco de dados.
Acesse agora a folha de cdigo do ServerMetodos e localize a parte superior da unit onde encontramos os
mtodos ReverseString e EchoString. Esses dois mtodos podero ser acessados por nossos aplicativos mveis, bem
como outros mtodos que venhamos a codificar nessa rea.
Para finalizar tudo, salve agora o projeto como DataSnapServer. Utilize a opo File > Save Project As. Em seguida
compile e execute nosso servidor utilizando Shift+Ctrl+F9 para rodar fora do modo Debug. Voc ver que basta clicar
no boto Start para que ele entre em ao e passe a escutar nossas requisies.

Aplicao Cliente
Agora aprenderemos apenas como fazer a configurao e conexo com nosso servidor de aplicativos DataSnap.
Mantenha o servidor aberto para que possamos fazer as configuraes.
#Dica: Clique com o boto direito do mouse em ProjectGroup1 no Project Manager e em seguida selecione Save Project
Group As para salvar o grupo de projetos.
Clique duas vezes em nosso projeto LodadoraDelphi.exe para que possamos selecionar o projeto Mobile. Ns
precisaremos incluir uma nova Unit nesse projeto utilizando o menu File > New > Other > DataSnap Server e logo em
seguida selecione o item DataSnap RESTClient Module (Figura 3).

Figura 3. Criao do mdulo cliente

Na primeira tela apenas escolha apenas Local server e avance. A tela seguinte que nos interessa. Nela escolhemos qual
o tipo de projeto servidor queremos conectar. Com base em nossa escolha, o Delphi criar a Unit e os componentes
necessrios para acesso ao servidor de dados. Nesse caso temos as opes:
DataSnap stand alone server: Servidor DataSnap stand-alone, nossa escolha;
WebBroker and stand alone server: Servidores Web;
IIS Module: Esse tipo de servidor funciona atravs do IIS no Windows, Internet Information Services;
Apache module: Podemos ter nosso servidor DataSnap rodando sob plataforma Apache;
Do not know: Desconhecido. Exige maior conhecimento das rotinas do servidor.
Escolheremos ento, como mencionado, a primeira opo DataSnap stand alone server. Na tela seguinte, e ltima, ns
podemos testar nossa conexo bem como modificar ou apenas informar a porta correta para conexo.
Depois de finalizado, ns teremos uma nova Unit que salvaremos como UntModuloCliente. E d o nome a ele de
ModuloCliente. Ns podemos ter quantos mdulos cliente quisermos. Perceba que um nico componente foi includo
nesse formulrio. Esse componente, do tipo DSRestConnection, o responsvel por conectar-se com nosso servidor
de aplicaes. Clicando nele e observando suas propriedades, perceba que podemos a qualquer momento alterar a
porta de conexo na propriedade Port.
Caso voc deseje testar se a conexo funciona, basta clicar com o boto direito do mouse no DSRestConnection e
selecionar Test Connection. Ainda com o boto direito, clique em Generate DataSnap client classes. Esse principal

__________________________________________________________________________________________
54

segredo do DataSnap. Clicando nessa opo, uma nova Unit ser gerada. Chamaremos essa Unit de Proxy, pois o que
ela faz. Esse proxy tem o objetivo de nos linkar com os mtodos do servidor. atravs dele que recebemos e
enviamos parmetros, datasets, etc entre cliente e servidor de aplicativos. Salve essa Unit com o nome que desejar,
mas eu prefiro cham-la simplesmente de Proxy.pas.
#Dica1: Sempre que uma nova funo for criada, excluda, tiver seus parmetros modificados ou ainda possuir novas
classes para serem exportadas/importadas, utilize o boto direito do mouse e a opo Generate DataSnap client
classes.
#Dica2: Na dica acima, apenas no se esquea que o servidor precisa estar aberto e iniciado.
#Dica3: A Unit Proxy.pas NUNCA deve ser alterada manualmente. No necessrio.
Figuras 4 e 5.

Figura 4. Escolhendo o tipo de servidor

Figura 5. Testando e finalizando a criao do Mdulo Cliente


#Dica: Como ns alteramos os nomes das duas novas Units, ou seja, UntModuloCliente e Proxy, precisaremos
tambm refazer a declarao dessas unidades que se enxergam. Para isso, acesse a seo Uses do UntModuloCliente
e acrescente a unit Proxy. Compile o projeto. Um erro ocorrer apontando para o nome antigo de nosso Proxy.
Apenas apague-o. Nosso Uses ficar semelhante ao cdigo abaixo:

__________________________________________________________________________________________
55

?
1
2

uses
System.SysUtils, System.Classes, Proxy, IPPeerClient, Datasnap.DSClientRest;

Testando o retorno de mtodos


Pois bem, at aqui no digitamos uma s linha de cdigo. Para finalizarmos nosso tutorial de hoje, faremos apenas um
pequeno de teste para entendermos o primeiro conceito de acesso ao servidor de aplicativos.
Retorne ao frmMain, formulrio principal de nossa aplicao mobile, e adicione um novo item de ListBox em nosso
menu principal. Ser provisrio, apenas para testarmos. Aumente a altura desse novo item de modo que caibam 1(Um)
Label, 1(Um) Edit e 1(Um) SpeedButton. Deseje nosso item semelhante a Figura 6.

Figura 6. Menu para teste


Antes de iniciarmos a codificao, precisamos fazer uso da Unit UntModuloCliente, por isso entre em File > Use Unit e
selecione a unit informada. No modifiquei o nome de nenhum componente.
No cdigo do boto SpeedButton1 codifique como mostrado a seguir:
?
1
2
3
4

procedure TfrmMain.SpeedButton1Click(Sender: TObject);


begin
Edit1.Text := ModuloCliente.SrvServerMetodosClient.ReverseString(Edit1.Text);
end;

Perceba como o cdigo simples. Abra a unit ModuloCliente e note que h uma propriedade chamada
SrvServerMetodosClient, que nada mais que uma referncia a nossa classe TSrvServerMetodos no lado servidor.
Atravs dessa propriedade conseguimos acesso ao mtodo ReverseString. Passamos para ela o valor digitado no Edit1
e recebemos do servidor a String invertida que substitui o contedo do prprio Edit.
Esses so os passos e conceitos padres para acesso ao servidor. No prximo tutorial, faremos a exportao de
um TFDJSONDataSet do servidor para o cliente e com ele alimentaremos uma tabela temporria do lado cliente.
Para no avanarmos demais nessa sexta parte, finalizaremos aqui e continuaremos nosso desenvolvimento na parte
VII.

Concluses
O uso de DataSnap uma mo a roda para quem deseja separar sua aplicao em camadas. Aqui vimos que
perfeitamente possvel efetuar chamadas ao servidor de aplicativos utilizando a porta 8080 e ler o retorno do servidor
em aplicaes mobile.Nossa aplicao est preparada para funcionar tambm em Desktop Windows ou Mac apenas
adicionando essas plataformas em nosso Project Manager, o que nos d tranquilidade para migrar nossa app para n
plataformas. At a prxima!

__________________________________________________________________________________________
56

Criando meu app step-by-step Reflection Parte VII

Reflection, novo conceito de desenvolvimento de servidores DataSnap com RAD Studio XE e FireDAC. Mencionei isso
no post passado referente ao Tutorial: Criando meu app step-by-step DataSnap Parte VI quando disse que iramos
avanar um pouco mais em nosso tutorial. Pois bem, chegou a hora. Nessa stima parte de nossa sequncia, veremos
como exportar um DataSnap do servidor para o cliente em formato FDJSONDataSet, nova classe no RAD Studio XE.
Tambm vimos a criao do nosso banco de dados Firebird 2.5 em nossa vdeo-aula complementar no YouTube nos
preparando j para fazer o sincronismo entre servidor e cliente. Vejamos o que foi dito na verso anterior desse post.
Criao do servidor DataSnap;
Criao do mdulo de conexo com o servidor DataSnap;
Teste de conexo.
Nessa stima parte, faremos a exportao da primeira tabela do banco no lado servidor, bem como seu uso no lado
cliente. Veja:
Criao da tabela do banco de dados no Firebird;
Criao dos mtodos de exportao de Ttulos no lado servidor;
Leitura e atualizao da tabela Ttulos local no dispositivo mvel;

Requisitos:
Leitura: Leitura do artigo parte VI;
Vdeo: Assistir ao vdeo complementar da parte VI;

Criando a tabela no banco de dados Firebird


A primeira providncia a ser tomada aqui criar nossa primeira tabela no banco de dados Firebird. Sendo assim,
faremos a abertura do banco no IBExpert. No entrarei em detalhes quanto ao uso de outras ferramentas de acesso
ao SGDB Firebird, pois est fora do escopo de nosso projeto.
#Dica: O IBExpert uma excelente ferramenta de acesso ao Firebird e Interbase e possui uma verso Personal FREE,
que possui recursos limitados, mas suficientes para a maioria das aes que precisamos fazer. Basta cadastrar-se no
nesse linke ento receber sua cpia FREE.
Com o IBExpert aberto e seu banco devidamente conectado, clique com o boto direito do mouse em Tables e em
seguida em New Table. direita e acima, voc encontrar o campo para nomear nossa tabela. Ele estar com o valor
NEW_TABLE. Modifique-o para TITULOS.
Crie a tabela do banco exatamente igual a que criamos para a verso SQLite, se preferir confira a Figura 1 que mostra
a tabela criada no IBExpert. A nica diferena est nos campos de imagem, FOTO e MINIATURA que so do
tipo BLOB com Sub_Type = BINARY.

Figura 1. Tabela Ttulos no Firebird

Reflection do FireDAC Configurao do servidor DataSnap


Conforme podemos ver no ttulo desse artigo, veremos um novo conceito de desenvolvimento de nosso servidor
DataSnap: Reflection. Um classe foi recentemente adicionada ao Delphi para esse propsito presente na
unit Data.FireDACJSONReflect. Ns podemos agora fazer a exportao de DataSets do servidor para o cliente de uma
maneira mais simples e ao mesmo tempo mais inteligente. Por exemplo: se precisarmos enviar diversos DataSets do
servidor para o cliente em uma nica instruo, basta usarmos TFDJSONDataSetsem um Function e podemos adicionar
mais de um DataSet ao Result da funo. Veremos isso mais delalhadamente, por enquanto vamos fazer a exportao
apenas de um nico DataSet, a tabela de pedidos.

__________________________________________________________________________________________
57

Para isso faremos agora as configuraes necessrias para acessar o servidor de banco de dados Firebird usando o
componente FDConnection. Abra o servidor DataSnap criado no artigo anterior e encontrei nosso ServerMethod que
tem o nome UntServerMetodos. nele que colocaremos nossas tabelas e conexes com o Firebird.
claro que o mais certo seria isolarmos os nossos Queries de demais componentes de acesso, como o FDConnection,
mas para nosso exemplo, no precisaremos dessa abordagem. Apenas insira um FDConnection no ServerMethod e d
o nome de FDConexao a ele. Em seguida clique duas vezes no componente para configurarmos suas propriedades de
acesso.
Na parte superior da janela, selecione o combo referente ao Driver ID e escolha FB. Feito isso, o Delphi modificar os
parmetros na parte de baixo para que sejamos capazes de configurar os dados de acesso. Em DataBase configure
incluindo o endereo completo do arquivo de banco de dados, em nosso caso LOCADORASERVER.FDB. E seguida
configure seu usurio e senha, SYSDBA e masterkey, respectivamente. Em Protolo, marque TCPIP. Clique em Test para
verificar se est tudo ok com a conexo. No nosso caso, estamos usando o Firebird 2.5, conforme demonstrado em
vdeo-aula. Observer a Figura 2 as configuraes bsicas.

Figura2. Conexes com o servidor DataSnap


Agora basta incluir no ServerMethod um componente do tipo FDQuery, para que possamos fazer uma Query na tabela
TITULOS para exportarmos para o servidor. D o nome de qryTitulos a esse query e escreva a seguinte instruo SQL
em sua propriedade de mesmo nome.
?

SELECT * FROM TITULOS

Bem simples, no? Exato, no queremos complicar nada nesse momento, apenas aprender a exportar o DataSet. Certo,
agora vamos fazer a function de retorno dessa tabela. Pressione F12 para ver o cdigo-fonte e procure a seo Public.
Declare a nossa function como na linha a seguir:
?

function GetTitulos: TFDJSONDataSets;

Perceba que estamos usando a classe TFDJSONDataSets como retorno da funo. Agora, precisamos pressionar CTRL
+ SHIFT + C para que o Delphi crie o escopo de nosso mtodo. Escreveremos o cdigo da Listagem 1.
?
1
2

function TSrvServerMetodos.GetTitulos: TFDJSONDataSets;


begin

__________________________________________________________________________________________
58

3
4
5
6
7
8

//Devolve para o cliente o DataSet de Pedidos


//Elimina cache
qryTitulos.Active := False;
Result := TFDJSONDataSets.Create;
TFDJSONDataSetsWriter.ListAdd(Result, qryTitulos);
end;

Listagem 1. Cdigo de exportao do DataSet TITULOS


Moleza para entendermos. Primeiramente ns fechamos a Query qryTitulos para evitar enviarmos ao cliente algo que
j esteja em cache. Em seguida ns criar uma instncia de TFDJSONDataSets (nosso resultado) associando-o ao Result
do mtodo.
Por fim, usamos a classe TFDJSONDAtaSetsWriter para adicionar TODO o contedo da Query ao Result, ou seja, quantos
forem as linhas listadas no qryTitulo sero adicionados ao Result e consequentemente recebidos pelo cliente. Eu disse
linhas listadas, mas creio que no perceberam que no abrimos a query em momento algum certo? Pois bem, o
mtodo ListAdd j faz isso para ns, ento no se preocupe.
Evidentemente que em uma situao real, precisaramos, talvez, passar um parmetro do cliente para o servidor
informando um determinado filtro a Query, algo como: TRAGA OS TTULOS QUE NO ESTO ALUGADOS. Mas isso
assunto para mais tarde.
Compile o servidor e veja se tudo est correto.
#Dica: Provavelmente a classe TFDJSONDataSets no ser encontrada, resultando em um error compiler. Portanto,
adicione a unit Data.FireDACJSONReflect ao uses do nosso ServerMetodos.
#Dica: No esquea de clicar com o boto direito do mouse em nosso qryTitulos escolher Fields Editor e com a janelinha
aberta, clicar com o direito novamente e ento usar o Add all fields para que todos os campos da tabela sejam
adicionados.
Execute o servidor DataSnap em modo SEM Debug clicando com o boto direito no Project Manager e em seguida em
Run Without Debbuging (Figura 3)

Figura 3. Rodando o servidor em modo stand-alone

__________________________________________________________________________________________
59

Preparando o cliente para acesso


Primeira coisa que quero fazer aqui testar sua memria. No, no quero que abra nenhum dos artigos sobre games
da memria publicados aqui no site. Quero apenas que lembre-se. Fomos at o servidor DataSnap
e MODIFICAMOS nosso servidor incluindo novos recursos, nesse caso um novo mtodo. Ento, qual o primeiro passo
aqui para comear a enxergar esse novo recurso?
Se respondeu que devemos abrir a unit Modulo Cliente, clicar com o direito no DSRestConnection1 e em seguida em
Generate DataSnap client classes (Figura 4), Bingo! Acertou na mosca.

Figura 4. Atualizando o cliente


Precisamos fazer isso para que nosso Proxy seja atualizado com o novo mtodo, GetTitulos. Ao gerar novamente o
proxy, ele ser imediatamente aberto, bastando apenas salvar e fechar essa unit. Lembre-se, no precisamos alterar
nada no Proxy.

Preparando o Sincronismo
Nessa ltima parte desse artigo, avanaremos pouco, pois desejo detalhar mais a tela de sincronismo na parte VIII, que
ficar bastante grande. Faremos apenas o entendimento do que ser feito acrescido de um pouco de cdigo.
Retorne at a tela principal do sistema com o nome de frmMain. No captulo anterior, ns deixamos um item de ListBox
a mais para testarmos a conexo com o servidor. Quero apenas que apague o Label e o TEdit inserido e deixe o boto.
No cdigo do boto, quero que insira o cdigo da Listagem 2.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

procedure TfrmMain.spbSincronizarClick(Sender: TObject);


var
LDataSetList : TFDJSONDataSets;
begin
MessageDlg('Confirma sincronismo de dados?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
//Efetua o download da tabela TITULOS vinda do Servidor DataSnap
LDataSetList := ModuloCliente.SrvServerMetodosClient.GetTitulos;
//Prepara o MemoryTable temporrio
memTemporario.Active := False;
//Fazemos um teste para verifica se realmente h DataSet no retorno da funo
Assert(TFDJSONDataSetsReader.GetListCount(LDataSetList) = 1);
//Adicionamos o contedo do DataSet "baixado" ao Memory Table
memTemporario.AppendData(TFDJSONDataSetsReader.GetListValue(LDataSetList, 0));
end
);
end;

Listagem 2. Cdigo prvio de sincronismo


Muito bom. A explicao no longa, mas exige ateno. A primeira coisa que fazemos aqui declarar uma varivel
do tipo TFDJSONDataSets. Lembre-se de adicionar a unit referente a essa classe em nosso uses. Em seguida ns criamos
uma MessageDlg, mas h um porm nisso tudo que terei que dar uma pausa para explicar antes.

__________________________________________________________________________________________
60

Pausa para mtodos annimos


No RAD Studio XE7 houve uma pequena mudana no MessageDlg, agora ele precisa de um novo parmetro para saber
que uma janela Modal e que precisa obedecer a um retorno *O sim. Nesse caso, repare que estamos usando um
mtodo annimo, programao avanada do Delphi. No entendeu? Vamos separar as coisas ento:
Normalmente usamos um MessageDlg assim:
?
1
2
3
4

if MessageDlg('Confirma sincronismo de dados?', TMsgDlgType.mtConfirmation,


[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) = mrYes then
//fazemos algo
end;

Somente isso j fazia com que a aplicao parasse e aguardasse o usurio pressionar em Yes ou No, mas agora
diferente. Precisamos fazer um algo mais. Aps o ltimo parmetro, o HelpContext, passamos um mtodo annimo
para a MessageDlg, ou seja, criamos um PROCEDURE no ltimo parmetro, veja:
?
1
2
3
4
5
6
7
8

MessageDlg('Confirma sincronismo de dados?', TMsgDlgType.mtConfirmation,


[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
//faz algo
end
);
end;

Dessa forma, quando o Yes for detectado, o cdigo que ser executado o nosso procedure (const AResult:
TModalResult) []. Entraremos em mais detalhes em outros tutoriais. Apenas entenda a nova sintax.

Retomando o raciocnio
Em nosso mtodo annimo ns no temos muita codificao, repare. So apenas 4 (quatro) linhas, o resto
so comentrios. Pois bem, a primeira coisa que fazemos receber na varivel LDataSetList a lista de DataSets recebida
do servidor com o uso do mtodo GetTitulos. Nesse caso estamos recebendo apenas UM DataSet. Depois de fazer isso,
ns fechamos o MemoryTable. Adicionei um FDMemoryTablena janela, pois receberemos o contedo da Query do
Servidor e adicionaremos dentro do MemoryTable no cliente, assim podemos fazer qualquer coisa com ele depois.
A prxima linha apenas um teste para nos certificarmos de que realmente a lista de DataSets possui ao menos um
DataSet. Fazemos isso usando um Assert.
Por fim, usamos o mtodo AppendData do MemoryTable para adicionar TODO o contedo do DataSet TITULO ao
MemoryTable. O AppendData j deixa o MemoryTable aberto, ou seja, nesse momento precisamos apenas montar um
LOOP para incluir esse dados em um banco de dados local. Bingo, nosso SQLite.
Na parte VIII de nosso Tutorial: Criando meu app step-by-step, faremos uso de ArrayDML para inserir rapidamente os
dados no nosso SQLite.

Concluses
Nessa stima parte de nosso tutorial, avanamos para o uso de Reflection do FireDAC como uma forma mais eficaz e
veloz de trazer informaes do servidor DataSnap para o cliente. Criamos nossa tabela do Firebird e j estamos prontos
para efetuarmos o sincronismo de dados.

O leitor Eduardo Belo fez um comentrio pertinente a um ponto de nosso tutorial. Assim como mencionado no vdeo
complementardesse post no YouTube, estamos utilizando a dll gds32.dll que refere-se ao Interbase, banco de dados
da Embarcadero. Entretando, na realidade nesse post usei o modo de retrocompatibilidade no momento da instalao
do Firebird 2.5. Isso faz com que o instalador renomeie a fdclient.dll para gds32.dll nos diretrios de sistema do
Windows.
Vale lembrar que o Firebird, para conhecimento dos leigos, derivado do Interbase, mas em um passado bastante
remoto. Para quem no sabe, o Interbase at sua verso 6.0 era gratuito e de cdigo-fonte aberto. Alguns
desenvolvedores russos copiaram o fonte e criaram o Firebird, que aos poucos foi se distanciando em termos de
funcionalidades em comparao ao Interbase. Hoje, so bastante diferentes.

__________________________________________________________________________________________
61

Criando meu app step-by-step ArrayDML Parte VIII

Estamos entrando na reta final de nosso Tutorial: Criando meu app step-by-step, e na parte VII iniciamos uma das
partes cruciais de nosso curso: O Sincronismo. Vimos como usar a classe TFDJSONDataSets para exportar dados do
servidor DataSnap para nosso aplicativo Mobile. Mas no vimos como fazer com que os dados recebidos sejam
inseridos no banco de dados local SQLite, veremos ento como utilizar comandos ArrayDML para fazer rapidamente
essas incluses.
Na parte VII ento vimos os seguintes tpicos:
Criao da tabela do banco de dados no Firebird;
Criao dos mtodos de exportao de Ttulos no lado servidor;
Leitura e atualizao da tabela Ttulos local no dispositivo mvel;
Como mencionado, veremos aqui os seguintes recursos:
Comandos ArrayDML para rpida insero no banco;
Ajustes na liberao de memria de objetos FORM;

Requisitos:
Leitura: Tutorial: Criando meu app step-by-step Parte VII

Criando meu app step-by-step ArrayDML Parte VIII


A grande maioria dos desenvolvedores Delphi que conheo tem como costume usar ClientDataSet e comandos do
tipo Append e Postpara criar rotinas de importao de dados em seus sistemas, isso porque mais prtico e rpido o
desenvolvimento de tais rotinas. Eu mesmo j cansei de criar ferramentas de importao usando esse mtodo.
Entretanto, sabemos que muito mais rpido fazer a importao usando comandos (instrues) SQL diretamente no
banco, haja vista que o banco processa as instrues com maior velocidade. Para os leigos, a explicao simples.
Para o uso de Appends e Posts (com aplicaes multi-camadas), normalmente necessrio usar uma estrutura
semelhante a Figura 1.

Figura 1. Estrutura bsica de importao de dados

Note que vemos uma estrutura bsica usando os quatro componentes base do DBExpress (existem milhares de outras
estruturas de componentes) onde normalmente nossas telas, a parte visual do sistema, se conecta
ao ClientDataSet1 que poderia ser por exemplo uma janela de clientes. O ClientDataSet Auxiliar (cdsAuxiliar) seria
usado para rodar um loop em dados temporrio fazendo a incluso em ClientDataSet1, algo como a Listagem 1.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

procedure TForm1.Importar;
begin
DataModule.cdsAuxiliar.First;
while not DataModule.cdsAuxiliar.EOF do
begin
DataModule.ClientDataSet1.Append;
DataModule.ClientDataSet1.FieldByName('CAMPO1').AsString := DataModule.cdsAuxiliar.FieldByName('CAMPO1').AsString;
DataModule.ClientDataSet1.FieldByName('CAMPO2').AsString := DataModule.cdsAuxiliar.FieldByName('CAMPO3').AsString;
DataModule.ClientDataSet1.FieldByName('CAMPO3').AsString := DataModule.cdsAuxiliar.FieldByName('CAMPO3').AsString;

DataModule.ClientDataSet1.Post;
DataModule.cdsAuxiliar.Next;
end;
DataModule.ClientDataSet1.ApplyUpdates(-1);
end;

__________________________________________________________________________________________
62

Listagem 1. Estrutura bsica de importao


Essa estrutura relativamente lenta em funo de um fator bastante simples de entender. Quando chamamos o
mtodo Post do DataSet(nesse caso um ClientDataSet) os dados so gravamos em memria, utilizando a memria do
computador que est executando o mtodo. Ao final do nosso loop, fazemos ento um ApplyUpdates, que informa
ao ClientDataSet que os dados devem ser empacotados e enviados ao o DataSetProvider. Todo esse processo exige
tempo, por isso a lentido.
Podemos executar comandos SQL diretamente no SQLConnection que nesse caso j nos dar um ganho de
performance de cerca de 30%, ou seja, 30% mais rpida a incluso no banco.
Mas creio que ficaro ainda mais surpresos quando disser que o mtodo utlizado com FireDAC e ArrayDML nos dar
um ganho de perfomance de at 60%. Isso mesmo! Nos meus testes consegui aumentar em 60% a velocidade de
importao de dados.

Entendendo o conceito
A estratgia de uso do FireDAC com ArrayDML para importao de dados ou simplesmente para qualquer insero de
dados direto no banco bem simples e de rpido entendimento. Vejamos.
No FireDAC, mais precisamente no FDQuery, temos o comando Execute assim como outros DataSets, mas nesse caso
podemos passar um nmero de inseres a ele e fazer o preenchimento de todos os parmetros da query de uma s
vez. Em nosso exemplo anterior, na parte VII de nosso tutorial, iniciamos a sincronizao usando o algoritmo
da Listagem 2.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

procedure TfrmMain.spbSincronizarClick(Sender: TObject);


var
LDataSetList : TFDJSONDataSets;
begin
MessageDlg('Confirma sincronismo de dados?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
//Efetua o download da tabela TITULOS vinda do Servidor DataSnap
LDataSetList := ModuloCliente.SrvServerMetodosClient.GetTitulos;
//Prepara o MemoryTable temporrio
memTemporario.Active := False;
//Fazemos um teste para verifica se realmente h DataSet no retorno da funo
Assert(TFDJSONDataSetsReader.GetListCount(LDataSetList) = 1);
//Adicionamos o contedo do DataSet "baixado" ao Memory Table
memTemporario.AppendData(TFDJSONDataSetsReader.GetListValue(LDataSetList, 0));
end
);
end;

Listagem 2. Algoritimo de sincronismo parte VII


Repare que paramos na parte que recebemos do servidor DataSnap os dados para importao e deixamos
um MemoryTable preparado para isso: memTemporario. Ele possui os registros da tabela TITULOS vinda da
base Firebird no servidor DataSnap. O que precisamos fazer aqui percorrer esse MemoryTable e ento incluir cada
registro da tabela em nossa tabela TITULOS no SQLite local.
Crie ento um novo procedimento chamado AtualizarTitulos recebendo um nico parmetro do tipo TFDMemTable,
como na linha abaixo:
?

procedure AtualizarTitulos(AMemoryTable: TFDMemTable);

Receberemos nesse mtodo a tabela que contm os dados a serem importados, ou seja, nosso memTemporario.
Pressione Ctrl + Shift + C para que o Delphi crie o escopo de nosso mtodo e vamos a codificao. Digite o cdigo
da Listagem 3.
?
1
2
3

procedure TfrmMain.AtualizarTitulos(AMemoryTable: TFDMemTable);


const
_INSERT =

__________________________________________________________________________________________
63

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

'INSERT INTO TITULOS


'(
'
ID_TITULO ,
'
TITULO
,
'
SUBTITULO ,
'
FOTO
,
'
MINIATURA
')
'VALUES
'(
'
:ID_TITULO ,
'
:TITULO
,
'
:SUBTITULO ,
'
:FOTO
,
'
:MINIATURA
');

' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
' +
';

var
intNumInserts : Integer;
begin
{Nmero de registros recebidos do servidor}
intNumInserts := AMemoryTable.RecordCount;
DM.qryAuxiliar1.Active
:= False;
DM.qryAuxiliar1.SQL.Text := _INSERT;
{Informamos a Query Auxliar qual o nmero de Inserts ser efetuado}
DM.qryAuxiliar1.Params.ArraySize := intNumInserts;
AMemoryTable.First;
while not AMemoryTable.Eof do
begin
DM.qryAuxiliar1.ParamByName('ID_TITULO').AsIntegers[AMemoryTable.RecNo-1] := AMemoryTable.FieldByName('ID_TITULO').AsInteger;
DM.qryAuxiliar1.ParamByName('TITULO')
.AsStrings [AMemoryTable.RecNo-1] := AMemoryTable.FieldByName('TITULO')
.AsString;
DM.qryAuxiliar1.ParamByName('SUBTITULO').AsStrings [AMemoryTable.RecNo-1] := AMemoryTable.FieldByName('SUBTITULO').AsString;
DM.qryAuxiliar1.ParamByName('FOTO')
.AsBlobs
[AMemoryTable.RecNo-1] := AMemoryTable.FieldByName('FOTO')
.AsVariant;
DM.qryAuxiliar1.ParamByName('MINIATURA').AsBlobs
[AMemoryTable.RecNo-1] := AMemoryTable.FieldByName('MINIATURA').AsVariant;

AMemoryTable.Next;
end;
{Se houver mais de um registro a ser aplicado, ento chama o Execute da Quuery Auxiliar}
if intNumInserts > 0 then
DM.qryAuxiliar1.Execute(intNumInserts, 0);
DM.qryAuxiliar1.Active := False;
end;

Listagem 3. Cdigo de sincronismo atualizado


A princpio parece longo o cdigo e talvez confuso, mas acalme-se porque fcil. Logo de incio criamos uma constante
chamada _INSERT que receber a instruo SQL INSERT para executarmos no servidor (nesse caso local). No entrarei
em detalhes, sobre os comandos.
Em seguida declaramos uma varivel que receber a quantidade de registros presente no MemoryTable,
o RecordCount. Isso ser usado para alimentar a subpropriedade ArraySize de Params. O que queremos dizer aqui
que teremos um array de contedos de campos para a LISTA de parmetros de cada registro. Preenchemos esse array
com o contedo de cada campo e por ltimo executamos.
Repare que efetuamos um Loop do MemoryTable e preenchemos cada parmetro usando seu respectivo tipo de dados
no plural (O plural foi apenas para chamar a ateno do leitor), veja:
?
1

DM.qryAuxiliar1.ParamByName('ID_TITULO').AsIntegers[AMemoryTable.RecNo-1] :=

Nos colchetes passamos o RecNo -1 (o array comea em 0 (zero)) do registro da MemoryTable no momento de cada
interao do Loop. E recebemos o valore referente ao campo da tabela em questo.
Aps terminar o loop, ns precisamos apenas executar a query usando o mtodo Execute do qryAuxiliar1. O primeiro
parmetro serve para indicarmos quantas vezes ser executado o comando, nesse caso o nmero de registros
presentes no MemoryTable. O segundo parmetro deixamos em 0 (zero) pois indica ao query que iremos comear as
inseres a partir do primeiro registro.

__________________________________________________________________________________________
64

Por fim apenas fechamos a tabela. Esse mecanismo pode ser usado para basicamente qualquer insero em lote que
voc precise efetuar em seus sistemas.
A ltima providncia que devemos tomar retornar ao evento do boto Sincronizar e adiciona a linha abaixo para fazer
a chamada ao mtodo AtualizarTitulos.
?
1
2
3

//Chamamos a rotina para incluir os dados recebidos na tabela Temporria,


//dentro da tabela no SQLite.
AtualizarTitulos(memTemporario);

Otimizando Memria
Vamos voltar no tempo at a primeira parte de nosso tutorial. Ns criamos um mtodo
no frmMain chamado ShowForm que recebe um TFmxObject como parmetro. Esse mtodo responsvel por abrir
os formulrios de nosso aplicativo mvel. Recordemos o cdigo:
?
1
2
3
4
5
6
7
8

procedure TfrmMain.ShowForm(AObject: TFmxObject);


var
I : Integer;
begin
for I := 0 to Pred(Self.lytMain.Children.Count) do
TControl(Self.lytMain.Children[I]).Visible :=
TControl(Self.lytMain.Children[I]) = TControl(AObject);
end;

Listagem 4. Cdigo do ShowForm


A codificao aqui bem simples como podemos ver. Apenas estamos deixando todos os formulrios invisveis, exceto
o formulrio recebido no parmetro. Entretanto temos um problema aqui, memria. Por enquanto temos apenas um
formulrio a mais, frmTitulos. Quando tivermos mais formulrios poderemos ter problemas de estouro de memria,
algo que em Desktop pode ser facilmente ignorado pois temos mais processamento e mais memria, embora no seja
uma boa prtica manter MemoryLeaks.
?
1
2

if not Assigned(FTitulos) then


FTitulos := TfrmTitulos.Create(Self);

Pegando como exemplo o item de menu Titulos, vemos que estamos fazendo um primeiro teste para verificar se existe
instncia do formulrio de ttulos e o criamos usando um Create(Self). A liberao de memria desse formulrio,
definitiva, fazemos no OnClose do formulrio principal.
?
1
2

if Assigned(FTitulos) then
FTitulos.DisposeOf;

At aqui nenhum problema e nenhuma novidade. Iniciantes e usurios Avanados do Delphi iro concordar que no
h nada de novo. Mas precisamos pensar na hiptese iminente de termos mais formulrios. Quando isso acontecer,
no podemos deixar nossos forms sempre ativos na memria, pois como mencionado anteriormente, poderemos
receber mensagens de erros e um grande problema com MemoryLeaks. Resolvi esse problema de forma at simples,
embora trabalhosa.
#Dica: MemoryLeaks, para os leigos, o estouro de memria na aplicao, ou seja, objetos no liberados de memria.
Vamos l. No mesmo evento ShowForm criaremos uma lista de objetos a serem destrudos e ento os liberaremos de
memria. Para comearmos essa rotina, primeiro precisamos de um novo formulrio. Pegando a ideia inicial de nosso
app, vamos criar um novo formulrio chamado frmUsuarios. Clique em File > New > Multi-Device Form Delphi. Use HD
Form como template. Modifique a propriedade Name para frmUsuarios e salve a unit como UntUsuarios. No faremos
nada com o formulrio agora. Apenas o usaremos como parte de nossa rotina para testes em nossa verso 2
de ShowForm.
Lembre-se de retirar a varivel com o nome do formulrio na rea Interface do form. Localize a instruo no cdigofonte e apague-a.
?
1
2

var
frmUsuarios: TfrmUsuarios;

__________________________________________________________________________________________
65

Retorne ao formulrio principal e adicione o novo form a seo Interface usando File > Use Unit. Crie uma nova varivel
em Private com o nome FUsuarios do tipo TfrmUsuarios. No evento OnClick do segundo item de menu, digite o cdigo
da Listagem 5:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

procedure TfrmMain.lstitUsuariosClick(Sender: TObject);


begin
if not Assigned(FUsuarios) then
FUsuarios := TfrmUsuarios.Create(Self);
MultiView1.MasterButton := FUsuarios.spbBack;
{Foramos o fechamento do menu no clique do item}
MultiView1.HideMaster;
{Adiciona o Layout de Pedidos ao Layout Principal que controla tudo}
lytMain.AddObject(FUsuarios.lytUsuarios);
{Deixa todos os layouts invisveis e deixa o layout alvo visvel}
ShowForm(FUsuarios.lytUsuarios);
end;

Listagem 5. Cdigo de abertura do formulrio de usurios


Isso j ser suficiente para termos acesso aos usurios. Claro, precisamos trabalhar no form, mas isso deixarei a cargo
de cada um. O que quero que observem aqui a primeira linha do cdigo. Estamos testando a varivel FUsuarios e
criando o formulrio se ele no existir, como fizemos com o form de ttulos. Se executarmos o app, poderemos
alternar agora de usurios para ttulos e vice-versa, mas o formulrio de usurios sempre estar no ar, exceto quando
o usurio fechar a aplicao. O que faremos?
Acesse o mtodo ShowForm e vamos comear a trabalhar nele. Digite o cdigo completo da Listagem 6.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

procedure TfrmMain.ShowForm(AObject: TFmxObject);


var
I
: Integer;
strFRM
: String;
FListaForms : TStringList;
begin
FListaForms := TStringList.Create;
for I := 0 to Pred(Self.lytMain.Children.Count) do
begin
TControl(Self.lytMain.Children[I]).Visible :=
TControl(Self.lytMain.Children[I]) = TControl(AObject);
strFRM := UpperCase(TControl(Self.lytMain.Children[I]).Owner.Name);
if ((strFRM <> UpperCase(frmMain.Name)) and (strFRM <> UpperCase(FTitulos.Name))) and
not (TControl(Self.lytMain.Children[I]).Visible) then
{Adiciona na Lista de Destruio dos Forms}
FListaForms.Add(strFRM);
end;
for I := Pred(FListaForms.Count) downto 0 do
begin
if (Assigned(FUsuarios)) and (FListaForms[I] = UpperCase(FUsuarios.Name)) then
begin
FUsuarios.DisposeOf;
FUsuarios := nil;
FListaForms.Delete(I);
end;
end;
FListaForms.DisposeOf;
end;

Listagem 6. Cdigo modificado de ShowForm

Repare que fizemos modificaes significativas. Criamos duas variveis para receber o nome do formulrio e outra para
gerenciar os objetos que sero destrudos. Basicamente o que faremos detectar quando trocamos de um formulrio
para outro e destrumos o formulrio anterior, exemplo:
Quando o usurio acessar o menu Usurios / Clientes, criaremos o formulrio na memria.

__________________________________________________________________________________________
66

Ao retornar para Ttulos, destruiremos Usurios / Clientes.


Assim acontecer com outros objetos.
Nesse esquema, o nico formulrio que no ser destrudo, por ser nosso default, ser o de Ttulos. Por isso detectamos
quando estamos passando por sua instncia e no o destrumos.
Criamos a varivel FListForms do tipo TStringList e iniciamos o Loop que j tnhamos antes, porm com uma alterao.
A varivel strFRMrecebe o nome do formulrio da interao atual do Loop. Se esse formulrio NO for o formulrio
Principal nem Ttulos, adicionamos ele a lista de formulrios a serem destrudos ou no.
Aps o trmino do primeiro loop, fazemos um loop na lista de formulrios. Ai comea nossa mgica que no nada
complicada. Ns fazemos um loop de trs para frente na lista de formulrios (FListaForms). Se o formulrio estiver
criado em memria E for igual a iterao atual do loop, ento liberamos ele usando DisposeOf, marcamos sua varivel
como NIL e deletamos na lista de formulrios.
Eu j expliquei, mas no custa falar novamente. Usamos em Mobile o mtodo DisposeOf, recomendao encontrada
em eBooks do Marco Cant e outros autores. O .Free ou .FreeAndNil, como estamos acostumados, funciona,
entretanto pode demorar at que o sistema operacional passe pelo objeto e o libere de memria. Quem faz isso
o GarbageCollection (Coletor de Lixo) no Android e iOS. Para evitar que o formulrio demore para ser destrudo,
usamos DisposeOf que envia instruo ao sistema operacional para destruir imediatamente o nosso objeto. Isso
funciona no s para formulrios, mas para outras variveis e objetos. o que fazemos logo em seguida.
?
1

FListaForms.DisposeOf;

Com todas essas verificaes e cuidados, conseguimos manter um app mais fluido e confivel.

Concluses
Fizemos basicamente duas grandes modificaes nesse tutorial. Aprendemos a aproveitar o contedo recebido do
servidor DataSnap e inclumos os registros em nossa base de dados local usando ArrayDML. Tambm vimos como fazer
uma modificao significativa em nossa rotina de abertura de formulrios para evitar problemas de MemoryLeak no
futuro.

__________________________________________________________________________________________
67

Criando meu app step-by-step Botes de Hardware


Parte IX

A parte IX de nosso Tutorial: Criando meu app step-by-step traz a voc todos os detalhes para o uso de dois importantes
botes de hardware no Android, os botes Back e Menu. Esses botes so comuns e aparecem em todos os aparelhos
munidos de sistema operacional Android, sejam botes fsicos ou virtuais. O boto Home tambm existe e comum,
mas varia um pouco o uso em cada aparelho. O aparelho que usamos para testar nossas aplicaes por exemplo,
um Samsung Win Duos, possui todos esses botes em formato fsico, comum em aparelhos Samsung. Nosso Tablet
Multilaser por outro lado, possui apenas botes virtuais.
Como devem ter notado, essa fase de nosso tutorial ser mais light, mas no menos importante. Alm de vermos como
fazer uso dos botes Back e Menu em nosso aplicativo, aprenderemos dicas importantes relacionadas ao controle da
aplicao usando tais botes.
Para relembrarmos o que vimos na edio passada, veja abaixo em forma de tpicos. Ns vimos basicamente o uso
de ArrayDML e algumas dicas para liberao de memria.
Comandos ArrayDML para rpida insero no banco;
Ajustes na liberao de memria de objetos FORM;
E como mencionado, veremos aqui:
Como fazer uso dos botes Back e Menu?

Requisitos
Leitura: Artigos de I a VIII desse tutorial.

Botes de Hardware
Antes de codificarmos nosso sistema, vamos entender qual a ideia de usar os botes de hardware, em quais momentos
vamos utiliza-los e onde detectar o seu pressionamento. Se recapitularmos nosso app, vamos lembrar que temos
algumas telas que so acessadas via Menu Principal. Algumas delas possuem navegao, ou seja, botes virtuais
Prximo e Anterior. aqui que entra o boto Back.Queremos que ao tocar no boto, uma aba (TabControl) retorne. J
o boto Menu, vamos usa-lo em dois momentos:
1. Quando o usurio desejar abrir o Menu Principal;
2. E quando houverem menus Pop-up;
Agora, onde detectar que o usurio tocou nos botes? Os botes de hardware no Android precisam ser programados
manualmente, praticamente hardcoded, isso porque eles no tem como saber em qual tela estamos em nosso app e
muito menos para onde vamos. Outra coisa importante que temos um Form Principal que praticamente comanda o
app inteiro. Lembre-se da primeira parte do tutorial quando montamos a arquitetura de navegao. Temos
um TLayout no form principal e outro TLayout em cada nova janela, e ao abrir uma nova janela, ns adicionamos o
Layout do alvo ao Layout do form principal. (Figura 1)

__________________________________________________________________________________________
68

Figura 1. Exemplo de tela com menu

Em outras palavras, como se adicionssemos os demais formulrios ao formulrio principal, portanto o comando
central o Form Principal. Se colocarmos algum cdigo nos evento OnKeyUp do formulrio alvo, esse no ser
acionado, ao contrrio, o evento acionado ser o OnKeyUp do form principal. Por isso nele que programaremos tudo.
Selecione o evento OnKeyUp e clique duas vezes nele para iniciarmos a programao.
A primeira providncia declararmos uma nova varivel a esse evento.
FService do tipo IFMXVirtualKeyboardService. Essa varivel ser responsvel por verificar se o teclado est visvel, pois
se estiver, ignoramos os botes Back e Menu.
O escopo do nosso evento pode ser visto na Listagem 1.
?
1
2
3
4
5
6

var
FService : IFMXVirtualKeyboardService;
begin
end;

Listagem 1. Incio da codificao do OnKeyUp


Agora vamos implementar todo o mecanismo de deteco dos botes na Listagem 1. Continuemos a codificao
recebendo o estado do teclado na varivel FService. A primeira linha do evento OnKeyUp segue como abaixo:
#Dica: Para termos acesso aos TPlatformServices e a Interface IFMXVirtualKeyboardService, declare as units
FMX.VirtualKeyboard, FMX.Platform, FMX.Helpers.Android, FMX.Platform.Android, no uses do form.
?
1
2

{Recebe o estado do teclado virtual}


TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FSer

Em seguida comeamos toda a brincadeira. Para o boto Back basta checarmos o estado da varivel Key presente no
evento. Perceba que a assinatura do evento OnKeyUp possui um Sender, um Key e um KeyChar. Testaremos Key para
verificar qual tecla (ou boto) foi pressionada. Podemos usar apenas:
?
1
2

if Key - vkHardwareBAck then


//Codificao

Veja como simples. Para o boto menu, basta testarmos se o Key igual a vkMenu. O cdigo-fonte da Listagem
2 refere-se ao cdigo completo do nosso mecanismo, ento vamos entender uma por uma das chamadas.
?
1
2
3
4
5

procedure TfrmMain.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;


Shift: TShiftState);
var
FService : IFMXVirtualKeyboardService;

__________________________________________________________________________________________
69

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

begin
{Recebe o estado do teclado virtual}
TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService, IInterface(FService));
{Se o boto back pressionado e o teclado virtual ativo, no faz nada}
if Key = vkHardwareBack then
begin
if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then
begin
//Reservado, no faz nada
end
else
begin
{Verifica qual formulrio est ativo e ento chama o mtodo Voltar}
{Se NO estiver com a listagem de pedidos aberta}
{$Region 'Menu'}
if MultiView1.IsShowed then
begin
MultiView1.HideMaster;
Key := 0;
end
{$EndRegion}
{$Region 'Titulos'}
else if (FTitulos.lytTitulos.Visible) and not (FTitulos.tabctrlTitulos.ActiveTab = FTitulos.tbitemLisTitulos) then
FTitulos.PressionouVoltar
else if (FTitulos.lytTitulos.Visible) and (FTitulos.tabctrlTitulos.ActiveTab = FTitulos.tbitemLisTitulos) then
begin
MessageDlg('Deseja sair do aplicativo?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
if AResult = mrYes then
begin
{$IFDEF ANDROID}
MainActivity.finish;
{$ELSE}
exit;
{$ENDIF}
end;
end
);
end
{$EndRegion}
{$Region 'Preferncias'}
else if (Assigned(FPreferencias)) then
begin
MessageDlg('Deseja sair do aplicativo?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
if AResult = mrYes then
begin
{$IFDEF ANDROID}
MainActivity.finish;
{$ELSE}
exit;
{$ENDIF}
end;
end
);
end;
{$EndRegion}
Key := 0;
end;
end
{Boto Menu do Android}
else if Key = vkMenu then
begin
if (FService <> nil) and (TVirtualKeyboardState.Visible in FService.VirtualKeyBoardState) then
begin
//Reservado, no faz nada
end
{O menu est sendo mostrado, apenas fecha o menu}
else
begin
if MultiView1.IsShowed then
HideBackground
{Verifica se o Pedidos est sendo mostrado e no est na lista de pedidos, para ento abrir o menu}
else if (FTitulos.lytTitulos.Visible) then
FTitulos.PressionouMenu;
Key := 0;
end;
end;
end;

Listagem 2. Cdigo Completo


O cdigo no contempla todas as situaes, a ideia somente dar o caminho das pedras. Na primeira parte de nosso
cdigo referente ao boto Back, ns verificamos se o menu principal est aberto. Caso ele esteja, ns verificamos se o
menu principal est aberto, por isso a instruo MuiltiView1.HideMaster. Ela fecha o menu. Caso contrrio, passamos
a verificar qual janela est aberta. Fazemos isso usando as variveis de cada formulrio, ex. Se o layout principal
de FTitulos estiver visvel, significa que a janela de Ttulos est aberta no momento. Para que o menu back funcione,

__________________________________________________________________________________________
70

testamos tambm se estamos na aba tbitemListTitulos, nesse caso chamamos o mtodo PressionouVoltar do
formulrio Titulos. Esse mtodo dever ser criado como a seguir:
?
1
2
3
4
5

procedure TfrmTitulos.PressionouVoltar;
begin
if tabctrlTitulos.ActiveTab = tbitemDetalhes then
tabctrlTitulos.Previous();
end;

Perceba como simples. Aps verificar que o menu no est aberto e que no estamos na aba principal de Titulos, ns
chamamos o mtodo PressionouVoltar da tela alvo e deixamos que o mtodo decida o que fazer. Nesse caso
verificamos se a aba Detalhes est aberta, caso esteja, ento voltamos uma aba.
Dessa maneira faremos em todas as janelas, criando um mtodo PressionouVoltar e codificando o que queremos que
acontea, tela a tela. A mesma codificao, fazemos para a tela de preferncias de sistema, a nica diferena que
testamos se a janela est criada usando um Assigned na varivel do form, isso porque preferncias criada e destruda
sempre.
Retornando ao formulrio principal, o final da codificao diz respeito ao boto menu. Nesse caso testamos se o Key
igual a vkMenu,para ento fazermos os devidos testes. Em nosso exemplo, temos apenas um teste que referente a
janela Titulos. Caso ela esteja visvel, ento chamamos o mtodo PressionouMenu do prprio FTitulos, ou seja, mais
uma vez o controle dado ao formulrio. O mtodo PressionouMenu dever ser criado como a seguir:
?
1
2
3
4
5
6
7

procedure TfrmTitulos.PressionouMenu;
begin
if (tabctrlTitulos.ActiveTab = tbitemLisTitulos) then
frmMain.MultiView1.ShowMaster
else if (tabctrlTitulos.ActiveTab = tbitemLisTitulos) and (DM.qryTitulos.State in dsEditModes) then
imgFotoClick(imgFoto);
end;

Como mencionado, mais uma vez o formulrio tem o controle da situao. Aqui nesse caso estamos verificando qual
aba est aberta. Se a aba visvel for a principal, abrimos o menu principal. Se Detalhes for a aba visvel e estivermos em
modo de Edio, descemos o menu pop-up para que o usurio troque a foto do ttulo.
Basicamente s isso que precisamos fazer. Parece complicado, mas na verdade somente trabalhoso e precisamos
ter muita ateno na codificao. A ltima coisa a explicar aqui sobre a linha Key := 0 vista em vrios lugares no
cdigo da tela principal, OnKeyUp. Isso necessrio, pois se o Key no receber zero a aps o pressionamento, o evento
continuar a executar linha a linha e ento teremos problemas.
Fica agora ao seu gosto, codificar o restante das telas usando como base o cdigo explicado acima.

Concluso
O usurio Android est bastante acostumado a usar os botes de hardware para voltar telas ou abrir menus. Por isso
importantssimo que codifiquemos cada boto para que a navegao do app fique mais transparente. Em iOS isso
no possvel, isso porque existem poucos botes e o que exitem esto destinados a funes especficas. A Apple no
permite que voc utilize um boto de hardware para alguma funo diferente da que ele foi criado, exemplo. Um boto
para aumentar volume, apenas aumenta volume e nada mais. Recentemente a Apple liberou o uso do boto Aumentar
Volume para que seja usado em aplicativos de foto, nada mais.
Outro detalhe no mencionado na codificao foi a instruo MainActivity.finish; Essa instruo finaliza totalmente a
aplicao Android, como se fosse um Application.Terminate em aplicativos Desktop. Isso de muita importncia, s
com essa instruo garantimos que o app ser totalmente fechado e que todas as variveis, forms, etc sejam liberados
de memria. Em iOS isso no necessrio.
Caso tenha interesse em ver mais informaes sobre outros botes, verifique a DocWiki da Embarcadero.

__________________________________________________________________________________________
71

Criando meu app step-by-step Sincronismo Parte X


Final

Chegamos a ltima parte de nosso Tutorial: Criando meu app step-by-step. At agora vimos como fazer toda a parte de
criao do aplicativo desde a concepo, passando por layout at o download de uma tabela inteira vinda de um
servidor DataSnap apontado para uma base de dados em Firebird 2.5. Muitos leitores nos escreveram solicitando essa
ltima parte que seria a mais importante de todas: o Sincronismo. Nesse tutorial ns veremos como fazer a excluso,
atualizao e insero de novos ttulos no servidor Firebirdusando o aplicativo Mobile.
Na parte anterior vimos:
Comandos ArrayDML para rpida insero no banco;
Ajustes na liberao de memria de objetos FORM;
Como mencionado veremos a seguir:
Como criar um mtodo para excluir registros do aplicativo mvel e do servidor;
Como enviar novos registros do Mobile para o Servidor;
Como criar um ApplyUpdates dos dados locais para o servidor;

Requisitos:
Leitura: Tutorial: Criando meu app step-by-step Parte IX

Tutorial: Criando meu app step-by-step Sincronismo Parte X


Antes de iniciarmos nosso tutorial, vamos relembrar algumas partes importantes para que possamos dar continuidade,
comeando
pelo
nosso DataModule na
aplicao Mobile. Ns
temos
em
nosso DM apenas
um
componente FDConnection para acesso ao nosso banco de dados SQLite e duas queries. Uma para listar os ttulos da
locadora e outra para efetuar pesquisas. Em nosso evento OnCreate, ns atribumos as devidas configuraes de
acesso ao banco local e ento conectamos a ele. Podemos ver isso na Figura 1 e em nossa Listagem 1.

Figura 1. DataModule Mobile


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

procedure TDM.DataModuleCreate(Sender: TObject);


var
sPath: String;
begin
with fdcConexao do
begin
{$IF DEFINED(IOS) OR DEFINED(ANDROID)}
Params.Values['DriverID'] := 'SQLite';
Params.Values['OpenMode'] := 'ReadWrite';
try
sPath := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.s3db');
Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.s3db');
Connected := True;
except on E: Exception do
begin
ShowMessage(E.Message);
end;
end;
{$ELSE}
try
Params.Values['Database'] := '$(DB_LOCADORA_SQLITE)';
Connected := True;
except on E: Exception do
begin

__________________________________________________________________________________________
72

25
26
27
28
29
30

ShowMessage(E.Message);
end;
end;
{$ENDIF}
end;
end;

Listagem 1. OnCreate do DataModule


At o presente momento, nosso aplicativo capaz apenas de listar os ttulos j disponveis no aparelho celular assim
como fazer um breve sincronismo trazendo os ttulos do servidor para o aparelho celular atravs de um
boto Sincronizar presente na tela principal.
Em nossa janela de ttulos, ns preparamos para que ela possa mostrar os ttulos em uma lista e ao tocar nela podemos
ver seus detalhes. Em frmTitulos temos um TabControl com duas abas, tbitemTitulos e tbitemDetalhe como visto
na Figura 2.

Figura 2. Design da tela de Ttulos


Na aba Detalhes faremos a incluso, alterao e excluso de ttulos da tabela em questo. Teremos que criar alguns
mtodos no servidor para que possamos trabalhar essas integraes.
Retornando a tela principal, nosso boto Sincronizar temos a funo de buscar no servidor os dados atualizados e
gravar no banco de dados local. Vejamos o cdigo-fonte na Listagem 2.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

procedure TfrmMain.spbSincronizarClick(Sender: TObject);


var
LDataSetList : TFDJSONDataSets;
begin
MessageDlg('Confirma sincronismo de dados?', TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0,
procedure (const AResult: TModalResult)
begin
//Efetua o download da tabela TITULOS vinda do Servidor DataSnap
LDataSetList := ModuloCliente.SrvServerMetodosClient.GetTitulos;
//Prepara o MemoryTable temporrio
memTemporario.Active := False;
//Fazemos um teste para verifica se realmente h DataSet no retorno da funo
Assert(TFDJSONDataSetsReader.GetListCount(LDataSetList) = 1);
//Adicionamos o contedo do DataSet "baixado" ao Memory Table
memTemporario.AppendData(TFDJSONDataSetsReader.GetListValue(LDataSetList, 0));
//Chamamos a rotina para incluir os dados recebidos na tabela Temporria, dentro da tabela no SQLite.

AtualizarTitulos(memTemporario);
end
);
end;

__________________________________________________________________________________________
73

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

//Mtodo de atualizao
procedure TfrmMain.AtualizarTitulos(AMemoryTable: TFDMemTable);
const
_INSERT =
'INSERT INTO TITULOS ' +
'(
' +
'
ID_TITULO ,
' +
'
TITULO
,
' +
'
SUBTITULO ,
' +
'
FOTO
,
' +
'
MINIATURA
' +
')
' +
'VALUES
' +
'(
' +
'
:ID_TITULO ,
' +
'
:TITULO
,
' +
'
:SUBTITULO ,
' +
'
:FOTO
,
' +
'
:MINIATURA
' +
');
';
var
intNumInserts : Integer;
begin
{Nmero de registros recebidos do servidor}
intNumInserts := AMemoryTable.RecordCount;
DM.qryAuxiliar1.Active
:= False;
DM.qryAuxiliar1.SQL.Text := _INSERT;
{Informamos a Query Auxliar qual o nmero de Inserts ser efetuado}
DM.qryAuxiliar1.Params.ArraySize := intNumInserts;
AMemoryTable.First;
while not AMemoryTable.Eof do
begin
DM.qryAuxiliar1.ParamByName('ID_TITULO').AsIntegers[AMemoryTable.RecNo-1]
DM.qryAuxiliar1.ParamByName('TITULO')
.AsStrings [AMemoryTable.RecNo-1]
DM.qryAuxiliar1.ParamByName('SUBTITULO').AsStrings [AMemoryTable.RecNo-1]
DM.qryAuxiliar1.ParamByName('FOTO')
.AsBlobs
[AMemoryTable.RecNo-1]
DM.qryAuxiliar1.ParamByName('MINIATURA').AsBlobs
[AMemoryTable.RecNo-1]

:=
:=
:=
:=
:=

AMemoryTable.FieldByName('ID_TITULO').AsInteger;
AMemoryTable.FieldByName('TITULO')
.AsString;
AMemoryTable.FieldByName('SUBTITULO').AsString;
AMemoryTable.FieldByName('FOTO')
.AsVariant;
AMemoryTable.FieldByName('MINIATURA').AsVariant;

AMemoryTable.Next;
end;
{Se houver mais de um registro a ser aplicado, ento chama o Execute da Quuery Auxiliar}
if intNumInserts > 0 then
DM.qryAuxiliar1.Execute(intNumInserts, 0);
DM.qryAuxiliar1.Active := False;
end;

Listagem 2. Sincronizando dados


Apenas para relembrar, ns estamos criando uma varivel do tipo TFDJSONDataSets que a classe utilizada para
exportar os dados do servidor para o mundo externo, nesse caso para nosso cliente. Essa classe traz o
prprio DataSet aberto do servidor no cliente de acordo com os devidos filtros aplicados. Em seguida ns adicionamos
esse DS em nosso componente MemTable atravs do mtodo AppendData do componente. Feito isso basta
criarmos algum mtodo para percorrer os registros. o que fazemos no mtodo AtualizarTitulos. Aqui ns
percorremos a MemTable e adicionamos um a um no banco de dados local. Algo parecido pode ser efetuado no
servidor, ou seja, podemos enviar um FDJSONDataSets para o servidor e fazer o trabalho de incluso no banco.

Editando e Adicionando registros no cliente


Antes de iniciarmos o sincronismo, faremos com que nossa tela de ttulos se torne totalmente independente, ou seja,
poderemos incluir, excluir e alterar registros na tela do celular. Ns montaremos a tela completa de edio, inclusive a
incluso de fotos. Vamos l:
Nossa janela de ttulos a essa altura do campeonato deve conter um componente Layout chamado lytTitulos e dentro
dele um TabControl com o nome tbctrlTitulos. Caso ainda no tenha adicionado a aba de detalhes
nesse tabcontrol, faa isso agora. Ns precisamos de duas abas. Uma se chamar tbitemTitulos e a outra
tbitemDetalhe. Mude para a aba de detalhe e adicione a ela duas ToolBars. A primeira delas ficar alinhada ao topo e
a segunda abaixo da TabItem.
Na toolbar superior insira os seguintes componentes e configure-os de acordo com o descrito:
1. SpeedButton:

__________________________________________________________________________________________
74

1.
2.
3.
4.
2.
1.
2.
3.
4.
3.
1.
2.
3.
4.
4.
1.
2.
3.
4.
5.
1.
2.
3.
4.

o
o
o

o
o
o

Name: spbVoltar
StyleLookup: backtoolbutton
Align: left
Margins.Left: 8
SpeedBuuton:
Name: spbCancelar
StyleLookup: deletetoolbutton
Align: left
Margins.Left: 8
SpeedButton:
Name: spbSalvar
StyleLookup: donetoolbutton
Align: right
Margins.Right: 8
SpeedButton:
Name: spbEditar
StyleLookup: composetoolbuttonbordered
Align: right
Margins.right: 8
Label:
Name: lblTituloDet
StyleLookup: listboxheaderlabel
Align: Contents
Margins: todas em 8px
Na ToolBar inferior adicione um SpeedButton com o nome spbExcluir. Alinhe-o como Client e coloque 8px em todas as
margens dele. No corpo do TabItem adicione um ListBox com o nome lsboxDetalhe e o alinhamento
como Client. Adicione dois itens no lsboxDetalhe. No primeiro item adicione um componente TImage e alinhe-o a
esquerda com margens 8px em todos os lados. Em seguida aumente a altura do item de listbox para 105 na
propriedade Height. Nosso TImage dever ficar com os tamanhos de largura (width) e altura (height)prximos
de 89px.
Nesse mesmo item de listbox adicione um TLayout e coloque-o como alinhamento Client. Dentro desse layout adicione
outro ListBoxque conter dois novos itens. Insira em cada item um componente TEdit para cada campo da tabela
de Ttulos, ou seja, um para Ttulo e outro para SubTitulo, veja abaixo:
TEdit:
Name: edtTitulo
Align: Client
Margins: todas como 8px
TEdit:
Name: edtSubTitulo
Align: Client
Margins: todas como 8px
No segundo item do nosso listbox geral, lsboxDetalhe, adicione um label alinhado a esquerda com 8px de margem
esquerda. Depois insira um TEdit chamado de edtAno e alinhe-o direita. Feitos os ajustes, ns termos algo parecido
com a Figura 3.

__________________________________________________________________________________________
75

Figura 3. Aba de detalhe


Agora precisaremos criar os devidos mtodos para ativar e desativar botes e tambm para colocar em modo de edio
ou adio.

Editando os dados
A primeira providncia criarmos um mtodo para ativar e desativar os botes. Para isso, acesse a
rea Public do form e crie um mtodo com o nome AtualizarBotoes, como abaixo:
procedure AtualizarBotoes;
Pressione Ctrl + Shift + C para criar o escopo do mtodo e codifique-o como na Listagem 3. E vamos a explicao. Ns
deixamos os botes Voltar, Editar e Excluir visveis somente se estivermos em modo Browse, ou seja, visualizando os
dados. Os botes Salvar e Cancelar somente ficam visveis se estivemos em modo de edio. Ainda mudamos a
propriedade ReadOnly de alguns componentes para permitir digitao.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

procedure TfrmTitulos.AtualizarBotoes;
begin
spbVoltar.Visible
:= (DM.qryTitulos.State = dsBrowse);
spbEdicao.Visible
:= (DM.qryTitulos.State = dsBrowse);
spbExcluir.Visible
:= (DM.qryTitulos.State = dsBrowse);
spbCancelar.Visible
spbSalvar.Visible

:= (DM.qryTitulos.State in dsEditModes);
:= (DM.qryTitulos.State in dsEditModes);

edtTitulo.Enabled
edtSubTitulo.Enabled
edtAno.Enabled

:= (DM.qryTitulos.State in dsEditModes);
:= (DM.qryTitulos.State in dsEditModes);
:= (DM.qryTitulos.State in dsEditModes);

edtTitulo.ReadOnly
:= (DM.qryTitulos.State = dsBrowse);
edtSubTitulo.ReadOnly := (DM.qryTitulos.State = dsBrowse);
edtAno.ReadOnly
:= (DM.qryTitulos.State = dsBrowse);
if (DM.qryTitulos.State in
begin
edtTitulo.StyleLookup
edtSubTitulo.StyleLookup
edtAno.StyleLookup
lblTituloDet.Text
end
else
begin
edtTitulo.StyleLookup
edtSubTitulo.StyleLookup

dsEditModes) then
:=
:=
:=
:=

'editstyle';
'editstyle';
'editstyle';
'Editando...';

:= 'transparentedit';
:= 'transparentedit';

__________________________________________________________________________________________
76

29
30
31
32

edtAno.StyleLookup
lblTituloDet.Text
end;
end;

:= 'transparentedit';
:= 'Detalhes';

Listagem 3. AtualizarBotes
Acesse o evento OnClick do boto voltar e digite o cdigo abaixo para que possamos Cancelar a edio caso o usurio
deseje retornar para a tela anterior.
?
1
2
3
4
5
6
7

if DM.qryTitulos.State in dsEditModes then


DM.qryTitulos.Cancel;
DM.qryTitulos.Active := False;
DM.qryTitulos.Active := True;
tabctrlTitulos.Previous;

Uma providncia que poderamos criar aqui seria perguntar ao usurio com um MessageDlg se ele realmente deseja
sair
da
tela
e
cancelar
o
cadastro.
Mas
isso
fica
a
critrio
do
leitor.
No boto cancelar insira o cdigo:
?
1
2

DM.qryTitulos.Cancel;
AtualizarBotoes;

Assim ns cancelamos a edio e atualizamos os botes de tela. Em seguida vamos mexer no evento OnClick do
boto Salvar, veja como fica:
?
1
2
3
4
5

if DM.qryTitulos.State in [dsInsert] then


DM.qryTitulos.FieldByName('ID_TITULO').AsInteger := DM.GetIDFromTable('TITULOS');
DM.qryTitulos.Post;
AtualizarBotoes;

Aqui simples entendermos. Se o cadastro estiver em estado de insero, ou seja, cadastro novo. Ns chamamos o
mtodos de criao de ID para esse registro. Ento gravamos o registro e atualizamos novamente os botes da tela.
Por fim, codifique o boto Editar como a seguir:
?
1
2
3

DM.qryTitulos.Edit;
AtualizarBotoes;
edtTitulo.SetFocus;

Muito fcil, apenas editamos e atualizamos novamente os botes. Focamos em cima do primeiro edit para que o
teclado suba. O ltimo boto o de excluso. Nesse codificaremos como abaixo, mas voltaremos mais tarde aqui para
fazermos uma alterao.
?
1
2
3
4
5
6
7
8
9
10
11
12
13

MessageDlg('Confirma excluso do ttulo selecionado?', System.UITypes.TMsgDlgType.mtConfirmation,


[System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYES :
begin
DM.qryTitulos.Delete;
Self.spbVoltarClick(Sender);
end;
end;
end
)

Apenas perguntamos ao usurio se confirma a excluso e em caso positivo chamamos o mtodo Delete do Query e o
boto voltar automaticamente para que a tela seja atualizada. Ns teremos que voltar aqui mais tarde para poder
colocar a excluso tambm no servidor.
Se voc rodar sua aplicao nesse momento, tudo funcionar perfeitamente com exceo da parte de fotos que no
foi codificada ainda. Retorne a aba de listagem nessa tela e adicione um novo SpeedButton na toolbar superior. D o
nome de spbAdd nele e alinhe-o direita com Margin.Right igual a 8px. Seu StyleLookup ser addtoolbuttonbordered e
seu cdigo como a seguir:
?
1
2
3

DM.qryTitulos.Append;
tabctrlTitulos.Next;
AtualizarBotoes;

__________________________________________________________________________________________
77

Aqui apenas chamamos o mtodo de incluso do DataSet e mudamos para a aba de detalhes sem esquecer de atualizar
os botes de tela.

Atualizando e Selecionando fotos


Agora faremos a parte de seleo de fotos atravs da cmera ou da biblioteca. Insira na tela um
componente TActionList e clique duas vezes nele. Clique no boto de seta da janelinha que aparece e selecione New
Standard Action. Localize as opes Media Library e adicione um TTakePhotoFromLibraryAction e um
TTakePhotoFromCameraAction. D os nomes de actFotoBiblioteca e actFotoCamera,respectivamente.
No evento OnDidFinishTaking digite o cdigo para uso da foto, como abaixo:
?
1

DM.qryTitulosFOTO.Assign(Image);

Como isso ns estamos recebendo a foto tirada/escolhida pelo usurio e inserindo direto no respectivo campo da base
de dados. Por fim, v at o evento OnClick do imgFoto e adicione o cdigo abaixo:
?
1
2
3
4
5
6
7
8
9

if DM.qryTitulos.State in dsEditModes then


begin
frmMain.ShowBackground(Self.lytTitulos, lstitCancelarClick);
lstPopUpFoto.Visible := True;
lstPopUpFoto.AnimateFloat('position.y', 0);
lstPopUpFoto.BringToFront;
end
else
ShowMessage('Voc precisa estar em modo de edio!');

Perceba que bem fcil entendermos. Estamos primeiro verificando se a tabela est em modo de edio e ento
mostramos um pop-upmenu criado em aulas anteriores. Nesse pop-up ns teremos as opes Novo Foto, Biblioteca e
Cancelar. Basta voltar no tutorial que falamos disso e veja a codificao. Finalizamos por aqui.
Teste a aplicao e verifique se tudo funcionou.

Excluindo do servidor
Nossa brincadeira agora comea a ficar mais sria. At o momento estamos alterando somente no dispositivo mvel,
ou seja, se excluirmos algo no aparelho, o registro ser excludo apenas do aparelho. Quando o usurio fizer uma nova
sincronizao, o dado vir novamente. Ento voltemos ao cdigo-fonte do servidor e vamos criar um mtodo para
excluso. Acesse o nosso nico ServerMethodno servidor DataSnap e insira na rea Public o seguinte mtodo e
pressione Ctrl + Shift + C para criar o escopo do mtodo:
?
1

function ExcluirTitulo(ATitulo: Integer): Boolean;

Codifique esse mtodos como abaixo. Insira nesse ServerMethod um FDQuery e d o nome de qryAuxiliar. O que
estamos fazendo bem simples. Criamos uma constante com a instruo DELETE para excluir ttulo da base de dados.
Fechamos a query, inserimos o valor do parmetro ATitulo que ser enviado pelo Cliente e ento usamos
o ExecSQL. Caso d tudo certo, resultamos True, caso contrrio Falsepara que possamos enviar uma mensagem ao
usurio.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14

function TSrvServerMetodos.ExcluirTitulo(ATitulo: Integer): Boolean;


const
_DELETE = 'DELETE FOM TITULOS WHERE ID_TITULO =:ATITULO';
begin
try
qryAuxiliar.Active := False;
qryAuxiliar.ParamByName('ATITULO').AsInteger := ATitulo;
qryAuxiliar.ExecSQL;
Result := True;
except
Result := False;
end;
end;

Compile o servidor e execute. Em seguida inicie o servidor.

__________________________________________________________________________________________
78

Excluindo no cliente versus Excluindo no servidor


Retorne agora ao nosso cliente e vamos fazer as devidas alteraes para que possamos excluir o dado nos dois locais.
Abra nosso mdulo cliente onde o componente DSRESTConnection se encontra. Clique com o direito nele e mande
gerar novamente nosso arquivo de Proxy. Note que agora temos o mtodo ExcluirTitulo. Abra o formulrio frmTitulos e
vamos fazer a alterao no boto de excluso. Caso ainda no tenha includo a unit ModuloCliente ao formulrio,
acesse File > Use Unit e insira a unit que contem o componente DSRESTConnection.
Agora acesse o evento OnClick do boto de excluso e altere seu cdigo como abaixo:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

procedure TfrmTitulos.spbExcluirClick(Sender: TObject);


begin
MessageDlg('Confirma excluso do ttulo selecionado?', System.UITypes.TMsgDlgType.mtConfirmation,
[System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo], 0,
procedure(const AResult: TModalResult)
begin
case AResult of
mrYES :
begin
if ModuloCliente.SrvServerMetodosClient.ExcluirTitulo(DM.qryTitulosID_TITULO.AsInteger) then
begin
DM.qryTitulos.Delete;
Self.spbVoltarClick(Sender);
end
else
ShowMessage('Ocorreu um erro ao excluir!');
end;
end;
end
)
end;

Perceba que fizemos uma pequena alterao no miolo de nosso mtodo. Chamamos o server
mtodo ExcluirTitulo passando para ele o ID_TITULO do ttulo selecionado. Se o mtodo retornar verdadeiro, significa
que conseguimos excluir no servidor, ento exclumos tambm off-line. Caso contrrio, mensagem ao usurio.

ApplyUpdates no servidor
Agora entramos na reta final. Vamos fazer a primeira parte, o ApplyUpdates. Quem j est acostumado a desenvolver
com DBExpress e ClientDataSet, sabe que existe um mtodo chamado ApplyUpdates do ClientDataSet que faz o
trabalho de enviar as alteraes para o servidor de banco de dados. Ns teremos que criar nosso prprio mtodo de
atualizao do lado do servidor. Retorne ao servidor DataSnap e adicione um novo mtodo como abaixo:
?
1
2
3
4
5
6
7

procedure TSrvServerMetodos.ApplyUpdadesTitulos(const ADeltaList: TFDJSONDeltas);


var
LApply: IFDJSONDeltasApplyUpdates;
begin
LApply := TFDJSONDeltasApplyUpdates.Create(ADeltaList);
LApply.ApplyUpdates(sTitulos, qryTitulos.Command);
end;

O que ns fazemos aqui criar uma instncia da interface IFDJSONDeltasApplyUpdates para que possamos fazer
o apply. Instanciamos a varivel e ento chamamos o mtodo ApplyUpdates da Interface passando como parmetro o
nome da tabela gravado na constante sTitulos (const sTitulos = TITULOS) na rea Private no do servidor DataSnap. E
o segundo parmetro ns chamamos o mtodo Command do qryTitulos. Somente isso. O restante a prpria interface
faz o trabalho para ns. Gere novamente o servidor e execute-o.
Voltando ao aplicativo mobile, retorne no nosso mdulo cliente e ento atualize o arquivo Proxy. Antes de fazermos a
alterao,
precisamos
de
um
componente MemoryTable no DataModule principal.
Adicione
um
componente FDMemTable no DataModule e d o nome de memTitulos. Ns usaremos esse componente para receber
os dados alterados e envi-lo ao servidor. Ns precisamos alterar o boto Salvar. Volte no cdigo-fonte e ento
modifique-o como a seguir:
?
1
2
3
4
5
6
7
8
9
10

procedure TfrmTitulos.spbSalvarClick(Sender: TObject);


var
LDeltaList : TFDJSONDeltas;
LDataList : TFDJSONDataSets;
begin
if DM.qryTitulos.State in [dsInsert] then
DM.qryTitulos.FieldByName('ID_TITULO').AsInteger := DM.GetIDFromTable('TITULOS');
DM.qryTitulos.Post;

__________________________________________________________________________________________
79

11
12
13
14
15
16
17
18

LDeltaList := TFDJSONDeltas.Create;
LDataList := TFDJSONDataSets.Create;
TFDJSONDataSetsWriter.ListAdd(LDataList, DM.qryTitulos);
TFDJSONDeltasWriter.ListAdd(LDeltaList, sTitulos, DM.memTitulos);
ModuloCliente.SrvServerMetodosClient.ApplyUpdadesTitulos(LDeltaList);
AtualizarBotoes;
end;

O que ns fazemos aqui bem simples. Ns precisamos criar uma instncia da classe FDJSONDeltas. Essa instncia
receber os dados alterados da query para envio ao servidor. Tambm precisamos de uma varivel para receber os
dados em formato FDJSONDataSets. O que estamos fazendo adicionando os registros da query Titulos dentro do
componente memTitulos. Logo em seguida chamamos o mtodo ApplyUpdatesTitulos passando o LDeltaList como
parmetro. Feito isso o servidor receber a lista de Deltas e aplicar ao banco de dados.

Enviando novos registros


Na seo anterior, ns fizemos a parte de ApplyUpdates, como mencionado. Se voltarmos no tempo para falarmos
de DBExpress, vamos lembrar que o ApplyUpdates na verdade o envio de um pacote com Deltas dos registros
alterados, excludos e includos do ClientDataSet para o DataSetProvider. O Provider se encarregava de fazer o trabalho
de receber esses Deltas e criar as instrues UPDATE, DELETE e INSERT de acordo com o tipo de registro recebido. E
essas instrues so aplicadas ao banco de dados.
Com FireDAC e Reflection, o processo semelhante, mas evidentemente que no precisamos usar
o DataSetProvider, to pouco o ClientDataSet. Nosso nico deve usar a classe TFDJSONDeltas para extrair
o Delta da query e s ento enviar esses dados para o outro lado do sistema, o servidor. E ento aplicar esse pacote ao
banco como vimos.
Automaticamente, no precisamos fazer um mtodo para insero to pouco excluso. Nesse caso s fizemos um
mtodo para excluir, pois precisamos ter um retorno do servidor. Mas facilmente poderamos seguir apenas com a
opo ApplyUpdates.
Para um maior entendimento do processo, recomendo que leiam e testem o exemplo completo de Reflection presente
na pasta Samples do Delphi.

Concluso
Finalizamos aqui nosso Tutorial: Criando meu app step-by-step que iniciamos em RAD Studio XE6 e finalizamos em XE7
(ou XE8 que tambm funcionar normalmente). O que vimos nesse tutorial que com poucos detalhes e at com
pouca programao, conseguimos criar um aplicativo totalmente compatvel com iOS 32 e 64Bits, Android, Mac OS X
e Windows 32 e 64bits.
Desenvolver aplicativos para essas plataformas hoje muito mais simples do que podemos imaginar. E o melhor de
tudo, com um nico cdigo-fonte. Em nosso app, temos acesso a um banco de dados local SQLite e ainda inclumos a
funcionalidade de sincronismo com um servidor de aplicativos plugado em um Firebird 2.5.
Esperamos que esse tutorial tenha sido importante para voc leitor e que possa compartilhar para outros que desejam
aprender mais.
At a prxima
#GoToDelphi

Nessa ltima parte de nosso tutorial, alguns leitores detectaram problemas na funo ApplyUpdates e resolvemos
revisar o artigo. De fato, o ApplyUpdatesTitulos criado aqui no funciona perfeitamente, isso porque estamos tentando
extrair os Deltas do qryTitulos (Query), mas isso no possvel. A codificao utilizada no consegue extrair justamente
por no existirem Deltas em FDQuery. Para corrigir o problema, devemos fazer algumas alteraes no nosso projeto.
Vamos l:
A primeira alterao redirecionar todos os binds para o memTitulos presente em nosso DataModule. Ento, nosso
memTitulos dever possuir os campos da tabela Ttulos. Ns j adicionamos esses campos no FieldsEditor da qryTitulos,
por isso clique com o direito nesse componente e escolha Fields Editor. Selecione todos os campos, pressione Ctrl + C
para copia-los e feche-o. Em seguida clique com o direito no memTitulos e escolha Fields Editor. Clique com o direito
na janelinha e em seguida em Paste.
Agora volte ao formulrio ttulos, acione a janela de Binding e refaa todos os links de campos apontando-os para o
memTitulos, como na Figura 4.

__________________________________________________________________________________________
80

Figura 4. Links refeitos no binding.


Agora o que precisamos fazer refazer a codificao toda apontando para o memTitulos ao invs do qryTitulos. O
primeiro lugar que devemos mexer no OnCreate, onde abrimos a querie. Localize a linha onde fechamos e abrimos
a querie e troque por memTitulos onde for necessrio.
Localize ao longo do cdigo-fonte todos os lugares que fazem meno ao qryTitulos e altere.
A ltima e mais importante alterao, diz respeito ao boto Salvar da tela de edio. Esse cdigo precisamos dar uma
ateno maior.
Na Listagem 4 logo a seguir, ns podemos visualizar todo o cdigo que utilizamos para gravar os dados no banco local
e no servidor. O problema aqui que estamos tentando extrair o delta do qryTitulos, coisa que no ser possvel como
mencionamos anteriormente.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

procedure TfrmTitulos.spbSalvarClick(Sender: TObject);


var
LDeltaList : TFDJSONDeltas;
LDataList : TFDJSONDataSets;
begin
if DM.memTitulos.State in [dsInsert] then
DM.memTitulos.FieldByName('ID_TITULO').AsInteger := DM.GetIDFromTable('TITULOS');
DM.memTitulos.Post;
LDeltaList := TFDJSONDeltas.Create;
LDataList := TFDJSONDataSets.Create;
TFDJSONDeltasWriter.ListAdd(LDeltaList, sTitulos, DM.memTitulos);
TFDJSONDataSetsWriter.ListAdd(LDataList, DM.memTitulos);
ModuloCliente.SrvServerMetodosClient.ApplyUpdadesTitulos(LDeltaList);
AtualizarBotoes;
end;

Listagem 4. Cdigo Original do Salvar


Nossa codificao ficar ainda mais simples agora. Basta omitirmos as linhas referentes a varivel LDataList. Ento o
cdigo final ficar como na Listagem 5 abaixo:
?
1

procedure TfrmTitulos.spbSalvarClick(Sender: TObject);

__________________________________________________________________________________________
81

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

var
LDeltaList : TFDJSONDeltas;
//LDataList : TFDJSONDataSets; desnecessrio
begin
if DM.memTitulos.State in [dsInsert] then
DM.memTitulos.FieldByName('ID_TITULO').AsInteger := DM.GetIDFromTable('TITULOS');
DM.memTitulos.Post;
LDeltaList := TFDJSONDeltas.Create;
//LDataList := TFDJSONDataSets.Create; desnecessrio
TFDJSONDeltasWriter.ListAdd(LDeltaList, sTitulos, DM.memTitulos);
//TFDJSONDataSetsWriter.ListAdd(LDataList, DM.memTitulos); desnecessrio
ModuloCliente.SrvServerMetodosClient.ApplyUpdadesTitulos(LDeltaList);
AtualizarBotoes;
end;

Listagem 5. Cdigo alterado


Ainda precisamos fazer um ltimo passo, atualizar e abrir o memTitulos no nosso DataModule. Ns manteremos o
qryTitulos, mas precisamos pegar os dados dessa query e adicionar diretamente no memory table para que possamos
navegar e fazer as devidas manutenes nos registros.
Crie um novo mtodo em nosso DataModule no lado cliente. O mtodo ter a seguinte codificao:
?
1
2
3
4
5
6
7
8
9
10
11
12
13

procedure TDM.AbrirTitulos;
var
LDataSetList : TFDJSONDataSets;
begin
qryTitulos.Active := False;
qryTitulos.Active := True;
LDataSetList

:= TFDJSONDataSets.Create;

memTitulos.Active := False;
TFDJSONDataSetsWriter.ListAdd(LDataSetList, qryTitulos);
memTitulos.AppendData(TFDJSONDataSetsReader.GetListValue(LDataSetList, 0));
end;

Com isso, ns agora temos o processo completo de alterao funcionando perfeitamente no Android e iOS. Agora no
evento OnCreate do formulrio Titulos chame esse mtodo para que possamos abrir a tabela.
O cdigo-fonte disponvel no BitBucket j est atualizado para download.

__________________________________________________________________________________________
82

Potrebbero piacerti anche