10
02/12/2016 Artigos file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 1/10 TPostGresConnection – Conexão com o PostgreSQL – parte I Neste artigo vamos explorar um mundo interessante, que é o mundo de banco de dados, utilizando o consagrando sistema gerenciador de banco de dados PostgreSQL, utilizando os componentes Zeos e construindo um sistema destas classes de conexão orientado a objeto, explicando passo a passo os procedimentos de configuração e instalação destes frameworks para a correta compilação e funcionamento deste aplicativo. O objetivo é construir passo a passo um aplicativo de editor de artigos, onde possamos gerenciar os cadastros dos artigos cujo conteúdo será puro HTML, onde os artigos prontos serão inseridos no banco juntamente com os conteúdos respectivos, e também visualizados pelo aplicativo Delphi através de um objeto da classe THTMLViewer ﴾distribuído nos componentes PBear THtml﴿. Quando iniciar o processo de comunicação, um objeto da classe TConnection será instanciado no padrão de projeto Singleton ﴾ou seja, apenas uma instância dele deve ser executada, e somente ela﴿ e assim ela não poderá ser instanciada ou destruída manualmente – o aplicativo que fará isso automaticamente, com base no padrão de desenvolvimento de softwares chamado “inversão de controle” – o programa se encarrega de instanciar e destruir a classe, sem o consentimento do desenvolvedor, assumindo pra si o controle dessa classe. Desta forma, o construtor e destruidor deste objeto será chamado na seção initialization e finalization, respectivamente, e o aplicativo não conseguirá instanciar manualmente como uma classe comum. Após inúmeros testes de conexão e iniciativa própria pra conseguir funcionar a comunicação entre o Delphi e o PostgreSQL, resolvi escrever este tema pra ajudar aos desenvolvedores a não passarem pelo mesmo árduo caminho percorrido pra fazerem a sua primeira comunicação com este banco de dados – o problema notado é que o Delphi 7 ﴾utilizado no desenvolvimento﴿ é de 32 bits enquanto que a instalação do PostgreSQL foi de 64 bits – e portanto esse foi um problema mas rapidamente temos a solução pra ele, de forma prática – basta baixar o pacote zipado do PostgreSQL de 32 bits ﴾mas sem instalar﴿ e extrair em qualquer diretório – e quando for conectar as dll´s pelo Zeos apontar pra este diretório de 32 bits ﴾e não de 64﴿ e “mandar ver”, e pronto! A comunicação foi feita com sucesso! ﴾basta apontar pra dll “libpq.dll” de 32 bits na propriedade LibraryLocation do objeto de TZConnection. Esta dll geralmente se encontra na pasta “Bin” da instalação do PostgreSQL, por exemplo “C:\Program Files\PostgreSQL\9.6\bin”﴿. Falando assim até que foi fácil, mas realmente não é nada tão difícil; as classes foram construídas para o programador usufruir das melhores práticas da orientação a objetos, de uma forma profissional, prática, eficiente e produtiva. Explicações iniciais da InfraEstrutura O aplicativo contém uma infraestrutura de funcionamento abstrata, onde as classes que interagem com o formulário contêm regras negociais além de validações básicas de campos, forms, etc; e estas classes chamam uma classe abstrata de conexão e aguardam seu retorno, e em caso de sucesso a operação desejada é executada – mas isso sem se comunicar diretamente com o banco de dados e sem conhecer nada dele, pois como afirmamos isso é feito de forma transparente e abstrata através do carregamento do objeto de conexão de forma automática, apenas uma vez, quando o programa é inicializado chamado pela seção initialization dele – as classes que precisarem de conexão não vão nem referenciar ela, como por exemplo criando uma variável da classe de conexão e instanciando ela – pois ela já foi criada e estará disponível durante todo o ciclo de vida da aplicação, apenas uma cópia na memória assim como prevê o padrão de projeto Singleton, e por isso estará tudo pronto visto que será responsabilidade da aplicação este controle e não mais do desenvolvedor. Funciona basicamente assim: 1. É criada uma interface que define procedimentos básicos de comunicação – IConnection; 2. É criada uma classe que implementará o padrão Singleton, a TInvalidateDestroy; 3. É criada uma classe pra implementar uma conexão básica, a TConnection, que herdará das duas classes mencionadas acima ﴾TConnection=class﴾TInvalidateDestroy, IConnection﴿; 4. É criada uma classe, chamada TPostGresConnection, que pelo nome podemos ver que implementará uma conexão com o banco PostgreSQL – esta classe herdará de TConnection; 5. Esta classe TPostGresConnection irá ler os parâmetros de conexão obtidos de um arquivo XML ﴾utilizando a classe TNativeXML﴿; 6. Pra se comunicar, após a leitura do XML esta classe TPostGresConnection irá instanciar em modo de execução os componentes da biblioteca Zeos pra comunicar com o banco PostgreSQL e acessar também seus dados ﴾por exemplo: stored procedures, que na verdade no PostgreSQL são definidas como functions﴿; 7. São criadas agora as classes que utilizarão a TConnection, que serão as classes negociais – estas classes apenas chamarão a TConnection e mais nenhuma outra. Em tudo que elas precisarem de conexão com o banco a TConnection se responsabilizará de fornecer pra elas. 8. Estas classes negociais irão utilizar objetos de TClientDataSet e outros objetos que não sejam data‐aware pra exibição dos dados do banco, pois a ideia não é “prender” os dados do form com o dataset, e sim apenas deixá‐los em memória, a fim de que eles possam ser navegados em um objeto de TDBGrid sem problema de performance, utilizando os métodos first e last do objeto de TClientDataSet sem obter erros de “dataset unidirecional” e por aí vai, etc; 9. Assim, com esta infraestrutura o programa ficará melhor implementado com as características do padrão da orientação a objetos, tudo encapsulado e consequentemente uma melhor reutilização de código, trazendo mais produtividade pro desenvolvedor visto que tudo estará centralizado em apenas um lugar, automatizando o código‐fonte através da herança, polimorfismo, etc; tudo será melhor escrito, ou seja, com menos código, a classe nossa que implementará a classe de artigos pra carregar eles possuirão poucas linhas de construção, visto que a encapsulação será forte para outras classes ﴾a classe TConnection possuirá o “grosso” de toda a base de comunicação e gerenciamento de objetos com o formulário, por exemplo a população de dados para com a classe TClientDataSet﴿. Sem mais delongas, vamos a apresentação das telas principais de conexão com o PostgreSQL, uma tela de exibição de HTML através da classe THTMLViewer ﴾componente do pacote PBear HTMLViewer﴿ e finalmente uma tela que chamará a classe TConnection, carregando artigos em um objeto da classe TClientDataSet:

T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 1/10

TPostGresConnection – Conexão com o PostgreSQL – parte I

Neste artigo vamos explorar um mundo interessante, que é o mundo de banco de dados, utilizando o consagrando sistema gerenciador de banco de dados PostgreSQL, utilizando os componentes Zeos e construindo um sistema destasclasses de conexão orientado a objeto, explicando passo a passo os procedimentos de configuração e instalação destes frameworks para a correta compilação e funcionamento deste aplicativo.

O objetivo é construir passo a passo um aplicativo de editor de artigos, onde possamos gerenciar os cadastros dos artigos cujo conteúdo será puro HTML, onde os artigos prontos serão inseridos no banco juntamente com os conteúdosrespectivos, e também visualizados pelo aplicativo Delphi através de um objeto da classe THTMLViewer ﴾distribuído nos componentes PBear THtml﴿.

Quando iniciar o processo de comunicação, um objeto da classe TConnection será instanciado no padrão de projeto Singleton ﴾ou seja, apenas uma instância dele deve ser executada, e somente ela﴿ e assim ela não poderá ser instanciadaou destruída manualmente – o aplicativo que fará isso automaticamente, com base no padrão de desenvolvimento de softwares chamado “inversão de controle” – o programa se encarrega de instanciar e destruir a classe, sem o consentimento dodesenvolvedor, assumindo pra si o controle dessa classe. Desta forma, o construtor e destruidor deste objeto será chamado na seção initialization e finalization, respectivamente, e o aplicativo não conseguirá instanciar manualmente como umaclasse comum.

Após inúmeros testes de conexão e iniciativa própria pra conseguir funcionar a comunicação entre o Delphi e o PostgreSQL, resolvi escrever este tema pra ajudar aos desenvolvedores a não passarem pelo mesmo árduo caminhopercorrido pra fazerem a sua primeira comunicação com este banco de dados – o problema notado é que o Delphi 7 ﴾utilizado no desenvolvimento﴿ é de 32 bits enquanto que a instalação do PostgreSQL foi de 64 bits – e portanto esse foi umproblema mas rapidamente temos a solução pra ele, de forma prática – basta baixar o pacote zipado do PostgreSQL de 32 bits ﴾mas sem instalar﴿ e extrair em qualquer diretório – e quando for conectar as dll´s pelo Zeos apontar pra este diretóriode 32 bits ﴾e não de 64﴿ e “mandar ver”, e pronto! A comunicação foi feita com sucesso! ﴾basta apontar pra dll “libpq.dll” de 32 bits na propriedade LibraryLocation do objeto de TZConnection. Esta dll geralmente se encontra na pasta “Bin” dainstalação do PostgreSQL, por exemplo “C:\Program Files\PostgreSQL\9.6\bin”﴿.

Falando assim até que foi fácil, mas realmente não é nada tão difícil; as classes foram construídas para o programador usufruir das melhores práticas da orientação a objetos, de uma forma profissional, prática, eficiente e produtiva.Explicações iniciais da InfraEstrutura

O aplicativo contém uma infraestrutura de funcionamento abstrata, onde as classes que interagem com o formulário contêm regras negociais além de validações básicas de campos, forms, etc; e estas classes chamam uma classe abstratade conexão e aguardam seu retorno, e em caso de sucesso a operação desejada é executada – mas isso sem se comunicar diretamente com o banco de dados e sem conhecer nada dele, pois como afirmamos isso é feito de forma transparente eabstrata através do carregamento do objeto de conexão de forma automática, apenas uma vez, quando o programa é inicializado chamado pela seção initialization dele – as classes que precisarem de conexão não vão nem referenciar ela, comopor exemplo criando uma variável da classe de conexão e instanciando ela – pois ela já foi criada e estará disponível durante todo o ciclo de vida da aplicação, apenas uma cópia na memória assim como prevê o padrão de projeto Singleton, e porisso estará tudo pronto visto que será responsabilidade da aplicação este controle e não mais do desenvolvedor. Funciona basicamente assim:

1. É criada uma interface que define procedimentos básicos de comunicação – IConnection;2. É criada uma classe que implementará o padrão Singleton, a TInvalidateDestroy;3. É criada uma classe pra implementar uma conexão básica, a TConnection, que herdará das duas classes mencionadas acima ﴾TConnection=class﴾TInvalidateDestroy, IConnection﴿;4. É criada uma classe, chamada TPostGresConnection, que pelo nome podemos ver que implementará uma conexão com o banco PostgreSQL – esta classe herdará de TConnection;5. Esta classe TPostGresConnection irá ler os parâmetros de conexão obtidos de um arquivo XML ﴾utilizando a classe TNativeXML﴿;6. Pra se comunicar, após a leitura do XML esta classe TPostGresConnection irá instanciar em modo de execução os componentes da biblioteca Zeos pra comunicar com o banco PostgreSQL e acessar também seus dados ﴾por

exemplo: stored procedures, que na verdade no PostgreSQL são definidas como functions﴿;7. São criadas agora as classes que utilizarão a TConnection, que serão as classes negociais – estas classes apenas chamarão a TConnection e mais nenhuma outra. Em tudo que elas precisarem de conexão com o banco a TConnection

se responsabilizará de fornecer pra elas.8. Estas classes negociais irão utilizar objetos de TClientDataSet e outros objetos que não sejam data‐aware pra exibição dos dados do banco, pois a ideia não é “prender” os dados do form com o dataset, e sim apenas deixá‐los em

memória, a fim de que eles possam ser navegados em um objeto de TDBGrid sem problema de performance, utilizando os métodos first e last do objeto de TClientDataSet sem obter erros de “dataset unidirecional” e por aí vai, etc;9. Assim, com esta infraestrutura o programa ficará melhor implementado com as características do padrão da orientação a objetos, tudo encapsulado e consequentemente uma melhor reutilização de código, trazendo mais

produtividade pro desenvolvedor visto que tudo estará centralizado em apenas um lugar, automatizando o código‐fonte através da herança, polimorfismo, etc; tudo será melhor escrito, ou seja, com menos código, a classe nossa queimplementará a classe de artigos pra carregar eles possuirão poucas linhas de construção, visto que a encapsulação será forte para outras classes ﴾a classe TConnection possuirá o “grosso” de toda a base de comunicação e gerenciamentode objetos com o formulário, por exemplo a população de dados para com a classe TClientDataSet﴿.

Sem mais delongas, vamos a apresentação das telas principais de conexão com o PostgreSQL, uma tela de exibição de HTML através da classe THTMLViewer ﴾componente do pacote PBear HTMLViewer﴿ e finalmente uma tela que chamaráa classe TConnection, carregando artigos em um objeto da classe TClientDataSet:

Page 2: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 2/10

,

Figura 01. Conectando com o PostgreSQL – tela básica de comunicação com os componentes Zeos

Figura 02 – Exemplo distribuído no pacote PBear HTMLViewer, mostrando a utilização da classe THTMLViewer pra edição de documentos HTML.

Figura 03 – Tela principal de listagem de artigos, implementado pela nossa infraestrutura com base na classe singleton TConnection.

unit UnTArticle;

interface

uses Forms, Windows, Classes, SysUtils, DBClient, DB, Grids, StdCtrls, CheckLst,Dialogs, UnConnection, UnConst;

type TArticle = classprivate function ViewArticles: TDataSet;public procedure GetArticles(var myClientDataSet: TClientDataSet); constructor Create; destructor Destroy; override;end;

implementation

Page 3: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 3/10

TArticle

constructor TArticle.Create;begin inherited Create;end;

destructor TArticle.Destroy;begin inherited;end;

procedure TArticle.GetArticles(var myClientDataSet: TClientDataSet);begin Connection.GetDataSet(ViewArticles, myClientDataSet);end;

function TArticle.ViewArticles: TDataSet;begin Result := Connection.Execute(plpgsqlViewArticles);end; ...

unit UnConnection;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DB, DBClient, Grids, DBGrids, StdCtrls, ComCtrls, UnIConnection, UnConst;

type ESingleton = class(Exception);

TInvalidateDestroy = class(TObject) protected class procedure SingletonError; public destructor Destroy; override; end;

TConnection = class; TConnectionClass = class of TConnection; TConnection = class(TInvalidateDestroy, IConnection) private FRefCount: Integer; class procedure Shutdown; // Allow descendents to set a new class for the instance: class procedure SetConnectionClass(aConnectionClass: TConnectionClass); // Actual constructor and destructor that will be used: constructor SingletonCreate; virtual; destructor SingletonDestroy; virtual;protected function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public // Not for use ­ for obstruction only: class procedure Create; class procedure Free(Dummy: integer); procedure Close; class procedure Destroy(Dummy: integer); $IFDEF VER120 reintroduce; $ENDIF // Simple interface: class function NewInstance: TConnection; procedure GetDataSet(const myDataSet: TDataSet; var myClientDataSet: TClientDataSet); function Execute(const fObjectName: string): TDataSet; function GetConnection(const typeConnection: tDBConnection = (dbcPostGres)): TConnection; end;$IFNDEF VER120 $WARNINGS ON $ENDIF

function Connection: TConnection;

implementation

var ConnectionInstance: TConnection = nil; ConnectionClass: TConnectionClass = TConnection;

class procedure TConnection.SetConnectionClass(aConnectionClass: TConnectionClass);// Allow change of instance classbegin Assert(Assigned(aConnectionClass)); if Assigned(ConnectionInstance) then SingletonError; ConnectionClass := aConnectionClass;end;

class function TConnection.NewInstance: TConnection;// Single Instance function ­ create when first neededbegin // Assert(Assigned(ConnectionClass)); if not Assigned(ConnectionInstance) then ConnectionInstance := ConnectionClass.SingletonCreate; Result := ConnectionInstance;end;

constructor TConnection.SingletonCreate;// Protected constructorbegin inherited Create; Self := Self.GetConnection;end;

Page 4: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 4/10

ConclusãoVimos de uma forma prática e eficiente de como implementar uma conexão com o banco PostgreSQL, aprendendo a mostrar conteúdos HTML e editá‐los, tudo via componentes open‐source, até o banco que não tem custo algum, ou

seja, tudo de forma sem ônus algum para o desenvolvedor, construindo um projeto de gerenciamento de artigos, onde nesta parte vimos mais a explicação sobre a estrutura da classe conexão, como ela e outras classes que descendem dela seinteragem e como funciona a ideia do padrão de projeto singleton e a recuperação de dados para um objeto de TClientDataSet através da classe TArticle.

Serão distribuídos os fontes bem como os scripts de criação das tabelas do banco, que foi utilizada a versão 9.6 ﴾64 bits﴿ e o Delphi 7 ﴾32 bits﴿ e dll´s pra comunicação entre as duas ferramentas o PostgreSQL de 32 bits ﴾apenas baixado edescompactado, mas não instalado – é usado apenas pra fazer esta comunicação – o PostgreSQL utilizado foi o de 64 bits que foi baixado, descompactado e instalado﴿.

Ainda falta muita coisa pra implementar neste projeto, que será a continuação dos próximos, que serão o armazenamento dos artigos diretamente no banco ﴾através da tabela de sistema pg_largeobject﴿, exportação de artigos do bancopro computador ﴾download﴿, submissão de artigos e recuperação do texto HTML para armazenamento deste texto em outra tabela, envio de emails dos artigos da semana a assinantes e finalmente o prosseguimento da implementação da classeTArticle ﴾CRUD completo﴿ e a nova versão da classe TConnection para suporte a logs multi‐thread e gerenciamento de exceções com suporte a um trace completo, baseado nos componentes open‐source da JCL ﴾Project JEDI Code Library﴿.

Portanto, apresentei ao leitor desenvolvedor uma forma profissional de criação de uma infraestrutura capaz de comportar todo um gerenciamento de conexão com o banco PostgreSQL, utilizando vários recursos de visualização em puroHTML dentre outros. Esta foi apenas a primeira parte desta diversão, aproveitem, bons estudos porque esta área é muito grande e traz muitas ideias inovadoras !!

Criando uma Lista de Contatos com o Ionic – Parte 3

IntroduçãoO Ionic Framework é um framework open source para criação aplicativos mobile desenvolvidos através de páginas HTML e códigos JavaScript. O Ionic oferece uma biblioteca de componentes HTML, CSS e JavaScript otimizados para o

mundo mobile e um conjunto de ferramentas que fazem a interação de sua aplicação com o hardware de forma nativa. Nos artigos anterior nós aprendemos como criar uma lista de contatos. Lista de ContatosNosso aplicativo será uma lista de contatos que irá conter o nome, o sobrenome e o telefone das pessoas. Contará com uma tela para exibição da lista, uma página com os detalhes e uma para adição e remoção dos contatos. O ideal é

que você siga os artigos em sequência, então recomendo que você siga a parte 1 e 2 antes de continuar. Adicionando um identificadorComo no nosso próximo artigo será como conectar nossa aplicação à um banco de dados e também para que possamos fazer a edição de nossos contatos, o primeiro passo será adicionar um identificador único a cada contato. Isso vai

evitar que o contato errado seja editado já que não haverá nenhum contato com o mesmo identificador. Altere o array contatos do arquivo home.ts para:

...

this.contatos = [

"id": 1,

"nome": "Ricardo",

"sobrenome": "Crivelli",

"telefone": "+55 14 99999­9999"

,

"id": 2,

"nome": "João",

"sobrenome": "Silva",

"telefone": "+55 14 55555­5555"

,

"id": 3,

"nome": "Maria",

"sobrenome": "Souza",

"telefone": "+55 14 22222­2222"

]

...

Encontrando o contato no arrayO segundo passo será criar um método responsável por identificar o elemento no array e retornar seu índice, você deve colocar o código no home.ts:

findContatoIndex(id)

for (let i=0; i < this.contatos.length; i++)

if(this.contatos[i].id == id)

return i;

Page 5: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 5/10

return null;

Se o seu compilador exibir a mensagem “Property 'id' does not exist on type 'Object'.” basta alterar a declaração do array contatos para:

...

export class HomePage

private contatos = [];

constructor(

...

O método findContatoIndex irá iterar por todos os elementos do array contatos e verificar qual possui o mesmo identificador e então retornar a posição dele no array. Adicionando um identificadorO terceiro passo é alterar o contato na listagem, para isso iremos criar um método que irá chamar o findContatoIndex e então efetuar a substituição.

changeContato(contato)

let index = this.findContatoIndex(contato.id);

this.contatos[index] = contato;

Você deve estar perguntando como será feita a chamada deste método pelo nosso modal, certo? Todo modal quando é fechado dispara um evento chamado onDidDismiss e é através dele que iremos capturar as mudanças. Para isso

altere o método showDetalhe do arquivo home.ts para:

showDetalhe(contato)

let modal = this.modalCtrl.create(DetalhesPage, contato: contato );

modal.onDidDismiss(data =>

if(data != null)

this.changeContato(data);

);

modal.present(modal);

Criando o botão salvarQuase tudo pronto! Basta agora adicionar um botão para salvar as informações, isso pode ser feito em duas etapas, a primeira é o código que irá passar as informações para o evento onDidDismiss e a segunda é o botão em si, vamos

para o código primeiramente.Abra o arquivo datalhes.ts e adicione importe o ViewController que será o responsável por fechar o modal:

import NavController, NavParams, ViewController from 'ionic­angular';

Agora será preciso iniciar uma instância do ViewController no construtor:

constructor(

private navCtrl: NavController,

private navParams: NavParams,

private viewCtl: ViewController

)

E por último vamos criar os métodos responsáveis por fechar e salvar as alterações, note que a única diferença é que em um é passado o objeto alterado e no outro apenas nulo. Lembra‐se do if no método onDidDimiss?

save()

this.viewCtl.dismiss(this.contato);

close()

this.viewCtl.dismiss(null);

Agora faltam apenas os botões para acionarem os métodos save e close. Abra o arquivo detalhes.html e adicione os botões dentro da ion‐navbar:

Page 6: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 6/10

<ion­navbar>

<ion­title>Contato</ion­title>

<ion­buttons start>

<button ion­button (click)="save()">

<ion­icon ios="ios­checkmark" md="md­checkmark"></ion­icon>

</button>

<button ion­button (click)="close()">

<ion­icon ios="ios­close" md="md­close"></ion­icon>

</button>

</ion­buttons>

</ion­navbar>

Notou um elemento novo? O ion‐icon é super simples de ser utilizado e permite que você configure um ícone para cada plataforma, a lista completa dos ícones pode ser encontrada em https://ionicframework.com/docs/v2/ionicons/.

Graças ao ion‐icon o nosso botão irá assumir diferentes aparências dependendo da plataforma que o aplicativo estiver rodando, é possível inclusive configurar para que o ícone assuma uma imagem completamente diferente de uma plataformapara a outra, isso pode ser configurado através do atributo ios para configurar como o ícone irá se comportar nas plataformas da Apple ﴾iPhone e iPad﴿ e o atributo md para configurar como será exibido junto ao Material Design ﴾padrão dedesign desenvolvido pela Google﴿. A figura abaixo retirada do site do Ionicons representa muito bem a diferença entre uma plataforma e outra.

Figura 1. Representação dos ícones em diferentes plataformas. Fonte: https://ionicframework.com/docs/v2/ionicons. Criando o botão removerVamos aproveitar o botão remover para aprender como funciona o elemento ion‐item‐sliding. Ele é como uma lista com super poderes, pois como o próprio nome sugere ele possui um comportamento adicional quando deslizamos o

item para o lado. Para entender melhor vamos à implementação. Alltere o seu home.html para que ele fique igual ao código abaixo:

...

<ion­content padding>

<ion­card>

<ion­card­header>

Contatos

</ion­card­header>

<ion­list>

<ion­item­sliding *ngFor="let contato of contatos">

<ion­item (click)="showDetalhe(contato)">

contato.nome contato.sobrenome

</ion­item>

<ion­item­options side="right">

<button ion­button color="primary" (click)="remove(contato)">

<ion­icon ios="ios­trash" md="md­trash"></ion­icon>

Remover

</button>

<button ion­button color="secondary" (click)="showDetalhe(contato)">

<ion­icon ios="ios­create" md="md­create"></ion­icon>

Editar

</button>

</ion­item­options>

</ion­item­sliding>

</ion­list>

</ion­card>

</ion­content>

Na tag ion‐item‐options existe um trecho marcado em negrito que configura o lado a ser deslizado para que o painel seja exibido, no nosso caso ele irá aparecer ao deslizar da direita para esquerda. Você pode criar um ion‐item‐options

para os dois lados no mesmo item se você quiser. Note também que criamos dois botões, um para editar o contato que chama o mesmo método de quando apenas clicamos no nome do contato e um outro botão que será o responsável pordeletar o contato chamando o método remove﴾contato﴿ que será implementado no arquivo home.ts agora.

remove(contato)

Page 7: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 7/10

remove(contato)

let index = this.findContatoIndex(contato.id);

this.contatos.splice(index, 1);

A implementação é muito simples e bastante semelhante ao método changeContato﴾contato﴿. Na primeira linha é encontrado a posição do contato no array e na segunda linha é feito a remoção através do método splice que é nativo do

JavaScript.Para testar se está tudo funcionando corretamente clique em um contato e arraste da direita para esquerda para que o painel apareça igual à Figura 2.

Figura 2. O elemento ion‐item‐sliding em funcionamento. ConclusãoNesta terceira etapa aprendemos como é simples transportar variáveis entre as views e como utilizar novos elementos como ion‐item‐sliding para aumentar as funcionalidades de nossa aplicação. No próximo mês nós aprenderemos a

adicionar um novo contato e iniciaremos a conexão com o banco de dados. Espero que tenham gostado e até o mês que vem!

Android ­ Utilizando a câmera

Olá amigos do The Club, a partir deste mês começarei a redigir artigos práticos utilizando a ferramenta de desenvolvimento “Android Studio”. Recomendo a utilização desta IDE por se tratar da mais completa e atualizada quando o

assunto se diz respeito aos dispositivos móveis com o Sistema Operacional Android. Um dos recursos mais usuais presentes nos disposivos móveis ﴾tablets, celulares﴿ é o uso da Câmera. Um exemplo quando desenvolvemos aplicativos, é anecessidade de fotografar um produto para mostrá‐lo ao cliente. A partir disto, surgiu então a ideia de escrever este artigo, abordando todas as etapas para implementar este tipo de funcionalidade. Este primeiro irá criar a classe “Camera” juntocom os lay‐outs necessários apenas para a apresentação da Câmera dentro de uma “Activity”.

Estarei utilizando o “Android Studio 2.2.2” Build de Outubro de 2016 e o “Java 1.8.0_111”. Preparei o aplicativo para ser rodado a partir do Android 4.1. ﴾Por se tratar de uma versão mais estável e muito utilizada entre nossos leitores﴿.

Organizei o artigo da seguinte forma:‐ Modificação do arquivo “AndroidManifest.xml”‐ Criação do lay‐out principal.‐ Implementação da classe “CameraVisualizao”‐ Implementação da atividade principal “MainActivity”.

Criando o Exemplo Abra o Android Studio clicando em “File/New Project...” para a criação de um novo projeto. O primeiro passo seria atribuir um nome para a aplicação ﴾Ex: AppCamera﴿, um domínio ﴾Ex: thiago.example.com﴿, Nome do Pacote ﴾Ex:

com.example.thiago.appcamera﴿ e Localização ﴾Ex: C:\users\Thiago\AndroidStudioProjects\AppCamera﴿. Fiquem a vontade para configurar o projeto da forma que desejar. Ver Figura 01.

Figura 01: Configurações Iniciais. Na próxima tela definimos a versão da API do Android utilizada, ex: API 16 – Android 4.1 ﴾Jelly Bean﴿. No próximo passo conseguimos implementar algumas pré‐configurações em nossa “Activity”. Costumo escolher a opção “Empty

Activity”, q qual irá criar uma atividade vazia. Ver Imagem 02.

Page 8: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 8/10

Figura 02: Criando a Activity.

Finalizamos a criação do projeto com o nome da Atividade principal. ﴾Ex: MainActivity.java﴿ Modificação do arquivo “AndroidManifest.xml”Deveremos adicionar duas linhas importantes neste arquivo responsáveis por permitir o uso e implementação da câmera no aplicativo.Ver listagem 01 com o código identificado.

<?xml version="1.0" encoding="utf­8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.thiago.appcamera" >

<uses­permission android:name="android.permission.CAMERA" /> <uses­feature android:name="android.hardware.camera" />

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" > <intent­filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent­filter> </activity> </application></manifest>

Listagem 01.Criação do lay­out principal.O nosso lay‐out principal será composto por um “FrameLayout” e dentro do mesmo mais um “Framelayout” e um “ImageButton”. Assim teremos a câmera ocupando a tela toda da tela do dispositivo e com um pequeno botão ﴾X﴿ para

fechar o aplicativo. Ver Imagem 03.

Figura 03: Lay­out proposto.

Implementação da classe “CameraVisualizao”A classe supracitada será responsável por englobar todos os métodos principais para o funcionamento de nossa câmera. Primeiramente deveremos importar algumas bibliotecas essenciais para o bom funcionamento. Listagem 02.

import android.content.Context;import android.hardware.Camera;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import java.io.IOException;public class CameraVisualizacao extends SurfaceView implements SurfaceHolder.CallbackEsta classe pública CameraVisualizacao irá herdar da “SurfaceView” e implementar da “SurfaceHolder.Callback” declarando os métodos: “SurfaceCreated”, “SurfaceChanged” e“SurfaceDestroyed”private SurfaceHolder mHolder;private Camera mCamera;

public CameraVisualizacao(Context context, Camera camera)super(context);mCamera = camera;mCamera.setDisplayOrientation(90);mHolder = getHolder();mHolder.addCallback(this);mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);

O método construtor irá receber dois parâmetros, sendo: O Contexto e o objeto Camera. Dentro do mesmo iremos setar algumas propriedades como por exemplo aorientação do visor ﴾“setDisplayOrientation”﴿.

@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder)trymCamera.setPreviewDisplay(surfaceHolder);mCamera.startPreview();catch (IOException e) Log.d("ERRO", "Problemas para criar o Preview da Câmera!" + e.getMessage());

No método sobrescrito “SurfaceCreated” iremos implementar um “try/catch” para definirmos a superfície a ser utilizada para visualização ﴾setPreviewDisplay﴿ e o início da captura e desenho dos enquadramentos para a tela ﴾startPreview﴿.

@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3)if(mHolder.getSurface() == null) return;

trymCamera.stopPreview(); catch (Exception e)trymCamera.setPreviewDisplay(mHolder);mCamera.startPreview();

Page 9: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 9/10

mCamera.startPreview(); catch (IOException e) Log.d("ERRO", " Problemas para criar o Preview da Câmera!" + e.getMessage());

O método “SurfaceChanged” é chamado quando a superfície tem suas características alteradas. Assim podemos redefinir a superfície a ser utilizada para visualização.

@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder)mCamera.stopPreview();mCamera.release();

Listagem 02.O método “SurfaceDestroyed” é invocado quando paramos a aplicação. Liberamos todos os objetos da memória.Implementação da atividade principal “MainActivity”.Esta Activity irá consumir a classe “Camera” e apresentá‐la na tela de nosso aplicativo. Listagem 03.

import android.hardware.Camera;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.FrameLayout;import android.widget.ImageButton;

Deveremos importar algumas bibliotecas para esta tarefa.

public class MainActivity extends AppCompatActivityprivate Camera mCamera = null;private CameraVisualizacao mCameraView = null;

Para implementar todas as funcionalidades usaremos duas variáveis privadas.

@Overrideprotected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);

trymCamera = Camera.open(); catch (Exception e)Log.d("ERRO", "Falha ao obter a Câmera: " + e.getMessage());

if(mCamera != null) mCameraView = new CameraVisualizacao(this, mCamera); FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view);camera_view.addView(mCameraView);

ImageButton imgClose = (ImageButton)findViewById(R.id.imgClose);imgClose.setOnClickListener(new View.OnClickListener() @Overridepublic void onClick(View view) System.exit(0););

Listagem 03.Todas as funcionalidades serão inseridas no método “OnCreate”. Através do método “Open” inicializamos a Câmera com o auxílio do “Try/Catch”. Instanciamos a classe “CameraVisualizacao” passando por parâmetro o Contexto e a

variável “mCamera”. Por final alimentamos o nosso layout.Não podemos esquecer da implementação do botão fechar, invocando o método “System.exit”.Podemos conferir o aplicativo em funcionamento na imagem 04.

Page 10: T/MPoodesl otPGDrF.easpsCx o n n e c t io n – C o n e x ã ...memória, a fim de que eles possam ser navegados em um objeto de T D B G r i d sem problema de performance, utilizando

02/12/2016 Artigos

file:///T:/Restrito/Revistas/BASE/ModeloPDF.aspx 10/10

Figura 04: Apilcativo em funcionamento.

ConclusõesA ideia principal deste artigo foi apresentar as funcionalidades básicas para a implementação do uso da câmera em aplicativos para o sistema Android. Utilizei bibliotecas específicas, como por exemplo: a “Camera”, a “SurfaceHolder” e a

“SurfaceView” e também realizei alterações importantes no arquivo “AndroidManifest”, a fim de chegar em um resultado esperado. Nos próximos artigos irei implementar outras funcionalidades com base no exemplo abordado neste mês.Um grande abaraço e até o mês que vem.

Sobre o Autor

TheClub

E­mail: [email protected]