News & Events
Tutorial: Criando meu app step-by-step – Parte III
No post anterior iniciamos uma das partes mais importantes de nosso aplicativo mobile com RAD Studio, o banco de dados. Aprendemos a iniciar a criação de nosso banco utilizando o SQLite, banco bastante popular em aplicações móveis, 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 aplicação 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:
- Criação do DataModule principal;
- Configuração dos principais componentes de acesso ao banco de dados;
- Criação dos métodos 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 vídeo: TDevRocks – Binding vs TListViews
Retomando o Raciocínio
Assim como mencionando anteriormente, iniciamos a criação 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 numérico 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 situação e fazer isso direto no código-fonte. Por isso criaremos uma função para nos retornar o ID do título.
Assim como em aplicações Desktop, é possível criar DataModules para separar nossos componentes visuais de componentes de acesso a dados. Inicie essa etapa entrando em File >> New > Other e escolhendo a opção 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. Após isso clique duas vezes nesse componente e observe a caixa de diálogo que se abre (Figura 2).
Figura 2. Diálogo de configuração do banco
Nessa janela somos capazes de fazer todo tipo de configuração 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 é compatível com diversos bancos, entre eles DB2, Firebird (FB), Interbase (IB), SQLServer (MSSQL), Oracle (ORA), entre outros tantos. Mas não se confunda. Atualmente os únicos bancos de dados que podem ser executados no dispositivo móvel (até o fechamento desse artigo, claro) são IBLite que é uma versão reduzida do Interbase para Mobile e o SQLite, que estamos tratando aqui. O fato, por exemplo, de termos acesso a Firebird, não significa que ele rodará em nosso dispositivo, o que tem causado bastante confusão em algumas pessoas.
Se você já tem um vínculo com nosso SQLite através do Data Explorer do Delphi (Janela ao lado direito do Delphi) então podemos vê-lo e seleciona-lo nessa caixa. Por hora apenas selecione SQLite em Driver ID.
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. Conexão com sucesso
Provavelmente se compilarmos o app nesse momento, nenhum problema será detectado, mas é provável que recebamos algumas mensagens de erro ao executar o app no Windows ou no dispositivo. Isso porque ainda precisamos declarar algumas units ou, mais fácil, incluir dois novos componentes que fazem o papel final de configuração do app. Insira um FDGUIxWaitCursor e n FDPhysSQLiteDriverLink. Não é necessária nenhuma configuração adicional. São na verdade os componentes que fazem o link final com o banco, não entrarei em detalhes. Por fim, desative a propriedade Login Prompt do fdConexao.
Agora, vamos fazer nossa primeira Query. Insira u FDQuery e dê o nome a ela de qryTitulos. Insira em sua propriedade SQL o seguinte código SQL.
SELECT ID_TITULO, TITULO, SUBTITULO, ANO_LANCAMENTO FROM TITULOS
Não entrarei em detalhes sobre instruções SQL, tomarei como verdade que todos tem o mínimo de noção sobre o SQL. Estamos fazendo aqui uma simples seleção de dados, apenas trazendo os campos da tabela. Caso deseje, também é possível clicar duas vezes no componente Query e abrir a janela de edição de SQL. Inclusive é possível fazer o teste de retorno de dados para verificar se a instrução está correta.
Após ter digitado a instrução, 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 mínimo de Delphi, não há novidades. Se preferir acesso campo a campo e modifique a propriedade DisplayFormat inserindo nomes mais amigáveis 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 aplicação se abre. Para isso costumo codificar diretamente no evento OnCreate do Data Module usando o código da Listagem 1.
procedure TDM.DataModuleCreate(Sender: TObject); begin with fdcConexao do begin {$IF DEFINED (IOS) || (ANDROID)} Params.Values['DriverID'] := 'SQLite'; try Params.Values['Database'] := TPath.Combine(TPath.GetDocumentsPath, 'Locadora.sqlite'); Connected := True; except on E: Exception do begin raise Exception.Create('Erro de conexão com o banco de dados!'); end; {$ENDIF} {$IFDEF MSWINDOWS} try Params.Values['Database'] := 'P:\tutoriais-tdevrocks\Curso-Completo\Parte III - SQLite\Database\Locadora.sqlite'; Connected := True; except on E: Exception do begin raise Exception.Create('Erro de conexão com o banco de dados!'); end; {$ENDIF} end; 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 não conhece, os iniciantes claro, essa palavra reservada permite que não precisemos mais digitar repetidas o nome de um objeto no bloco, exemplo:
Ao invés de usarmos toda hora:
fdcConexao.Params.Values.['DriverID']... fdcConexao.Params.Values['Database']... fdcConexao.Connected := True;
Nós simplesmente envolvemos o bloco inteiro com um:
with COMPOENTE do
Para mais de um componente, podemos incluir vírgulas:
with fdcConexao, qryTitulos, frmPrincipal do ...
Perceba inclusive que incluímos no exemplo anterior, frmPrincipal, ou seja, também são aceitos formulários.
Muito bem, estamos atualizando o parâmetro DriverID com o nome do driver de nosso banco, ou seja, SQLite. Em seguida atualizamos o parâmetro com o nome caminho completo do banco. Atenção apenas para alguns detalhes. Estamos usando Diretivas de Compilação para desviar o código de acordo com a plataforma.
{$IF DEFINED (IOS) || (ANDROID)}
Se for iOS ou (||) Android usamos TPath.Combine e TPath.GetDocumentsPath. Ambos os métodos pertencem ao namespace System.IOUtils, portanto declare essa unit na seção Interface da unit.
- TPath.Combine: Responsável por concatenar duas strings de endereço. Ele já faz o trabalho de descobrir, por exemplo, qual barra utilizar, já que há diferença entre iOS, Android e Windows;
- TPath.GetDocumentsPath: Descobre qual o endereço da pasta Documents no dispositivo móvel.
Sempre utilize esses dois métodos para buscar e concatenar diretórios no Mobile.
Por fim de tudo, conectamos ao banco de dados usando um Connected := True;
Envolvemos tudo isso em um Try…Except para evitar que algum problema aconteça sem que possamos notificar o usuário.
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á incluímos um FDQuery ao Data Module e codificamos a instrução SQL para trazer os dados de TITULOS. Agora precisamos ler essas informações em u TListView. Para isso, abra nosso formulário de títulos frmTitulos.pas.
Faça com que ele tenha vínculo 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 Títulos
Além disso, teremos que tomar outra providência: abrir a tabela Títulos. Faremos isso, por enquanto, no menu, portanto retorne ao frmMain, clique duas vezes no ListBoxItem correspondente ao nosso Menu Títulos e clique duas vezes para visualizarmos o código-fonte.
Adicione o código das linhas a seguir:
DM.qryTitulos.Active := False; DM.qryTitulos.Active := True;
Estamos fechando e abrindo novamente a tabela para forçar um “refresh”. Não esqueça de fazer um Use Unit nesse form, já que ele ainda não enxerga nosso Data Module.
Em outro momento faremos uma codificação para formar o DisposeOf dos formulários não visíveis em tela, evitando que tenhamos memória desnecessária sendo desperdiçada. Nesse momento transferiremos o código de abertura das queries para o Form Create de cada tela.
Antes de testar a aplicação, acesse o menu Project >> Options e em Form modifique a ordem de criação do frmMain e do DM como mostrado na Figura 5.. Estamos ainda sem foto para os títulos, que deverão aparecer ao lado esquerdo do TListView.
Figura 5. Ordem de criação dos formulários
Detalhes dos Títulos
Montaremos agora uma aba para mostrar os detalhes do nosso Título. Para isso adicione uma nova aba ao TabCtrl de Clientes clicando com o botão 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 também suas margens para 8px em todos os lados.
Ainda na primeira linha do ListBox, adicione um TLayout e dentro dele 2 (Labels). Eles serão nosso Título e SubTítulo respectivamente. Eles devem receber o Name e o Text como abaixo, assim como outras propriedades:
Label Título
- 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 Lançamento.
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:
tabctrlTitulos.Previous;
Esse botão será responsável por voltar a listagem de títulos. Agora sim marque o ListBox como Client e vamos ver o resultado. Nossa janela deverá possuir uma aparência semelhante a da Figura 6.
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 não aparece por Default, portanto localize o item de listbox na janela de Binding e clique no botão reticências dele, assim uma nova caixa de diálogo será aberta e basta marcarmos a propriedade Text e clicar em OK. O único que ainda não será ligado é o imgFoto, pois ainda não temos um campo de foto no banco de dados. Veja como todos os campos ficam ligados na Figura 7.
Figura 7.
Também não queremos que as abas na parte inferior sejam mostradas para o usuário final, então deixaremos elas na tela apenas em tempo de projeto para nos ajudar a desenhar e fazer as devidas manutenções. Mas em runtime sumiremos com elas assim como marcaremos como default a aba de Listagem. Entre no evento OnCreate desse form e digite o código a seguir:
tabctrlTitulos.TabPosition := TTabPosition.None; tabctrlTitulos.ActiveTab := tbitemLisTitulos;
Bem simples não? Estamos mudando a propriedade TabPosition para None, assim as abas não aparecerão. E também configuramos a ActiveTab como sendo a listagem. Retorne agora para a aba principal e selecione o evento OnItemClick do TListView. Digite o código para passar para a aba de Detalhes:
tabctrlTitulos.Next;
Um último retoque. Se executarmos agora o aplicativo, veremos que no lugar de “Ano Lançamento” aparece apenas o Ano, e o texto some. Então clique duas vezes no componente BindinsList1 e em seguida selecione o link correspondente ao Item de ListBox do Ano de Lançamento, provavelmente será o último. Pressione F11 para abrir o Object Inspector e selecione o campo CustomFormat. Digite na propriedade o texto a seguir:
'Ano Lançamento: ' + %s
Isso fará com que concatenemos a palavra ‘Ano Lançamento” 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 Vídeo 1 como ficou nossas alterações nessa terceira parte.
https://www.youtube.com/watch?v=8prlxrR64oA&list=UUDW0I8VdlHwn7uga53UcxtQ
Vídeo 1. Complemento de Tutorial
Conclusões
Nessa terceira parte de nosso tutorial, vimos como implementar o uso de tabelas reais de um banco SQLite para carregar informações em um TListView. Vimos também como facilmente criar um Layout para mostrar os detalhes de um item do ListView, nesse caso um Item selecionado pelo usuário final.
Na próxima etapa, veremos como fazer o primeiro CRUD (Funções de Inclusão, Exclusão e Alteração de Dados) no banco de dados.
O código-fonte desse exemplo pode ser baixado em:
https://bitbucket.org/tdevrocks/tutorial-criando-meu-app-step-by-step
Author: Adriano Santos
1 comentário
Comments are closed.
[…] #3 Segmenting Code In A Data Mobule And Connecting Controls To A Database Creating the main DataModule; Configuration of the main components for access to the database; Creation of methods of listing and Title Details Title; Assembly of functional screens. […]