jm63_jme_padroesprojetos

21
1/21 Aplicando Padrões de Projetos em Java ME Solucione problemas comuns encontrados em aplicações móveis utilizando padrões de projetos para a plataforma Java ME RAMON RIBEIRO RABELLO, PEDRO JORGE FERREIRA TRECCANI E THIENNE JHONSON De que se trata o artigo: Utilizar padrões de projetos específicos para a plataforma Java ME para geração de conteúdo interativo em MIDP. Para que serve: Fornecer uma alternativa para aplicação de padrões de projetos existentes ou específicos para a plataforma Java ME em aplicações móveis, com o intuito de resolver problemas enfrentados durante o desenvolvimento de GUIs para MIDlets. Em que situação o tema é útil: Caso deseje utilizar padrões de projetos em Java ME que minimizem a complexidade enfrentada durante o desenvolvimento de conteúdo gráfico interativo. Aplicando padrões de projetos em Java ME: A plataforma Java ME se tornou uma das tecnologias mais utilizadas para o desenvolvimento de aplicações móveis. Com a evolução das tecnologias dos dispositivos (aumento do poder de processamento, de armazenamento, etc.), o desenvolvimento de MIDlets deixou de ser ad-hoc e passou a seguir um caráter mais profissional e comercial, no qual “BluePrints” disponíveis para as outras especificações da linguagem Java como Java SE ou Java EE puderam ser aplicados também para a versão móvel do Java. Diante deste cenário, vários desenvolvedores móveis começaram a aplicar tais padrões de projetos em seus projetos e obtiveram casos de sucesso. E outros, dentre eles Ben Hui, desenvolveram padrões de projetos específicos para solucionarem problemas comuns enfrentados durante o desenvolvimento de interfaces gráficas em MIDP, que são: Cascading Menu, Wizard Dialog, Pagination e Slide Show.

Upload: caco3000

Post on 27-Sep-2015

3 views

Category:

Documents


0 download

DESCRIPTION

JM63_JME_PadroesProjetos

TRANSCRIPT

  • 1/21

    Aplicando Padres de Projetos em Java ME Solucione problemas comuns encontrados em aplicaes mveis utilizando padres de projetos para a plataforma Java ME

    RAMON RIBEIRO RABELLO, PEDRO JORGE FERREIRA TRECCANI E THIENNE JHONSON De que se trata o artigo:

    Utilizar padres de projetos especficos para a plataforma Java ME para gerao de contedo interativo em MIDP.

    Para que serve:

    Fornecer uma alternativa para aplicao de padres de projetos existentes ou especficos para a plataforma Java ME em aplicaes mveis, com o intuito de resolver problemas enfrentados durante o desenvolvimento de GUIs para MIDlets.

    Em que situao o tema til:

    Caso deseje utilizar padres de projetos em Java ME que minimizem a complexidade enfrentada durante o desenvolvimento de contedo grfico interativo. Aplicando padres de projetos em Java ME: A plataforma Java ME se tornou uma das tecnologias mais utilizadas para o desenvolvimento de

    aplicaes mveis. Com a evoluo das tecnologias dos dispositivos (aumento do poder de processamento, de armazenamento, etc.), o desenvolvimento de MIDlets deixou de ser ad-hoc e passou a seguir um carter mais profissional e comercial, no qual BluePrints disponveis para as outras especificaes da linguagem Java como Java SE ou Java EE puderam ser aplicados tambm para a verso mvel do Java. Diante deste cenrio, vrios desenvolvedores mveis comearam a aplicar tais padres de projetos

    em seus projetos e obtiveram casos de sucesso. E outros, dentre eles Ben Hui, desenvolveram padres de projetos especficos para solucionarem problemas comuns enfrentados durante o desenvolvimento de interfaces grficas em MIDP, que so: Cascading Menu, Wizard Dialog, Pagination e Slide Show.

  • 2/21 Os padres de projetos h muito tempo foram criados para solucionar problemas que ns,

    programadores, encontramos no desenvolvimento de cada dia, aumentando o nvel de modularidade, a reusabilidade e diminuindo o grau de acoplamento entre os mdulos ou componentes das nossas aplicaes. Estes padres (Design Patterns ou simplesmente Patterns) so muito utilizados e conhecidos nas

    plataformas Java SE e Java EE. Entretanto, o desenvolvimento de aplicaes mveis na plataforma Java ME tem amadurecido a cada dia, e BluePrints especficos para a confeco de aplicaes tm surgido. Tudo isso com o objetivo de diminuir o esforo no desenvolvimento de aplicaes que precisam ser executadas em dispositivos com caractersticas limitadas, como o caso dos telefones celulares e Smartphones. Este artigo ir demonstrar a viabilidade da utilizao de padres de projetos e como estes podem

    melhorar significativamente o desenvolvimento de MIDlets (aplicaes para o perfil MIDP). Para isso, sero apresentados quatro padres de projeto especficos para a plataforma Java ME: Cascading Menu, Wizard Dialog, Pagination e Slide Show.

    Restries em dispositivos mveis Programar para dispositivos mveis requer um pouco de cautela, haja vista as limitadas

    configuraes da maioria dos dispositivos. Restries como baixo poder de processamento, capacidade de memria limitada e escassez de recursos grficos ainda preocupam o desenvolvedor no momento de implementao da sua aplicao mvel Java ME. Em dispositivos celulares mais antigos, por exemplo, no h suporte para cores. Porm, h anos que os fabricantes de dispositivos produzem telefones celulares com suporte a cores. Com a evoluo da tecnologia, hoje comum encontrar um celular com suporte de 262 mil cores ou mais. Outro fator restritivo o limite da tela na maioria dos dispositivos. Por exemplo, em um celular que

    possui uma resoluo de 12.288 pixels (96 x 128), se torna difcil exibir um simples nome completo ou endereo de uma pessoa. Entretanto, o avano da tecnologia dos dispositivos mveis, principalmente a capacidade de

    armazenamento (hoje podemos armazenar gigas de dados) e a de processamento, aliada ao fenmeno da convergncia digital, tm proporcionado uma alternativa de melhoria no desenvolvimento de aplicaes mveis, sendo possvel elaborar arquiteturas mais robustas (vrias camadas) a serem utilizadas por MIDlets. Hoje em dia raro encontrar uma aplicao mvel que seja restrita a uma nica MIDlet (e talvez mais algumas classes utilitrias), onde possvel perceber claramente a mistura das regras de negcios com componentes de Interface Grfica com o Usurio, o que dificulta consideravelmente a reusabilidade e manutenibilidade. Portanto, para solucionar o problema, entram em cena os Padres de Projeto.

    Padres de projetos em Java ME Java ME, desde sua concepo, tem sido a plataforma preferida entre os desenvolvedores de

    aplicaes para dispositivos mveis, graas s suas mais variadas caractersticas que seguem o lema do WORA (Write Once, Run Anywhere escreva uma vez, execute em qualquer lugar), um dos fatores essenciais para a garantia da portabilidade da linguagem Java. Contudo, desenvolver aplicaes para dispositivos que suportam essa plataforma ainda desafiante. A evoluo das tecnologias dos dispositivos mveis quer seja de hardware ou de software vem possibilitando a construo de sistemas mveis cada vez mais complexos, que podem variar desde uma aplicao M-Commerce que realiza transaes bancrias at um jogo de estratgia. Com o passar dos anos, os desenvolvedores mveis foram adquirindo experincias nessa

    plataforma e perceberam que para implementar determinada funcionalidade era necessrio que tarefas semelhantes fossem replicadas por vrias linhas de cdigo, o que prejudicava a produtividade e tornava o desenvolvimento montono. Assim, perceberam que determinados padres de projetos poderiam ser adaptados para a plataforma Java ME e utilizados em suas aplicaes sem comprometer o propsito deles. Os prprios arquitetos da verso mvel de Java utilizaram alguns patterns para a construo da plataforma (veja o quadro O Padro Factory em MIDP).

  • 3/21 Outros desenvolvedores criaram seus prprios padres e aplicaram em suas aplicaes, relatando

    casos de sucesso na utilizao de tais padres. Um deles, chamado Ben Hui, elaborou quatro padres de projeto: Cascading Menu, Wizard Dialog, Pagination e SlideShow, os quais simplificam o desenvolvimento de contedo interativo usando o perfil MIDP (Mobile Information Device Profile). A seguir ser descrito cada padro. Para o desenvolvimento dos exemplos deste artigo, foi utilizada a IDE Eclipse 3.4 - Ganymede (www.eclipse.org/ganymede/) juntamente com o plugin EclipseME 1.7.9 (http://eclipseme.org/) e para a emulao, a ferramenta Sun Java Wireless Toolkit 2.5.2 for CLDC, para as especificaes CLDC 1.1 e MIDP 2.0. Os exemplos de cdigo dos padres de projetos mostrados neste artigo foram baseados nas implementaes do autor dos padres. O link para baix-los est disponvel na seo Links. Para cada padro de projeto apresentado, ser utilizado um quadro que mostra a arquitetura e descreve sucintamente o objetivo, o problema e sua soluo, os elementos que fazem parte do padro, a conseqncia da aplicao deste pattern e sua implementao. O padro Factory em MIDP Desde a concepo de Java ME que os projetistas utilizam o conceito de padro de projeto. Um exemplo disso o GCF (Generic Connection Framework ou Framework de Conexo Genrica), que como o nome sugere a estrutura que o MIDP utiliza para a realizao de vrios tipos de conexes. Este pattern deve ser aplicado quando no for possvel determinar o tipo de objeto que deve ser instanciado (como pode ser visto na Listagem 1). Sendo assim, o padro Factory (Fbrica) que caracterizado como um padro de projeto criacional pode ser utilizado para abstrair todo o trabalho de criao do objeto. No caso do GCF, percebemos claramente a presena deste padro por meio da Classe javax.microedition.io.Connector, na qual chamamos o mtodo Connector.open() e passamos como parmetro apenas uma string representando a URL ao qual queremos ter acesso. Depois, de acordo com o tipo de protocolo que for passado (HTTP, Socket, HTTPS, Bluetooth, etc.), o framework instancia uma classe especfica que implementa todas as funcionalidades referente quele protocolo. Para isso, o parmetro passado a Connector.open() deve estar no seguinte formato: {scheme}:[{target}][{params}], onde {scheme} representa o tipo de protocolo sendo acessado, {target} normalmente algum endereo de rede (www.algumsite.com.br, por exemplo) e {params}, os parmetros passados na URL no formato ;param=valor. A arquitetura com os principais componentes do GCF mostrada na Figura 1. Dessa forma, podemos tratar qualquer tipo de conexo como um Connection. Porm, caso queiramos, por exemplo, realizar uma conexo do tipo HTTP, deveremos realizar um cast para a interface HttpConnection. Ento, o framework se encarregar de instanciar a classe que implemente a interface HttpConnection, tudo isso de forma transparente para o desenvolvedor, graas ao padro Factory. A Listagem 1 mostra este pattern em ao no GCF, na qual passado como parmetro para o mtodo open() de Connector apenas uma String que indica a URL a qual ser realizada a conexo. De antemo, no se sabe qual ser o tipo de objeto retornado pelo mtodo, haja vista que este retorna uma interface (HttpConnection) em vez de uma classe concreta. Ento, o framework trata de analisar o protocolo de acordo com o esquema da url passada (que no nosso caso http://) e depois instanciar uma classe (esta classe ir variar de acordo com a implementao da CLDC do fabricante) que implemente todas as funcionalidades deste protocolo.

  • 4/21

    Figura 1. Arquitetura do GCF em MIDP. Listagem 1. Exemplo do padro Factory no GCF: FactoryPattern.java. public class FactoryPattern extends MIDlet implements CommandListener { private HttpConnection con; //pgina inicial do portal DevMedia public final String URL = "http://www.devmedia.com.br/portal/default.asp"; // outras declaraes de variveis private void conectar() { try { // Utilizao do padro Factory con = (HttpConnection) Connector.open(URL); con.setRequestMethod(HttpConnection.GET); // abre a conexo is = con.openInputStream(); // cdigo para tratamento dos dados retornados } catch (IOException e) { // tratamento adequado da exceo } } }

    Padro Cascading Menu Vrias so as maneiras de se implementar navegao em uma aplicao. Uma delas por meio de

    menus. Para a representao de cada menu, uma possvel implementao seria por meio de subclasses da classe javax.microedition.lcdui.List contendo vrias opes de escolha. Um exemplo interessante da utilizao do padro Cascading Menu seria em uma aplicao do tipo guia de cidades, no qual o usurio vai navegando por vrios menus at ser retornada alguma informao. No modelo de tratamento de eventos em Java ME, as classes que necessitem capturar o

    pressionamento de teclas devem implementar a interface javax.microedition.CommandListener

  • 5/21

    juntamente com seu mtodo commandAction(), e configurar o mtodo setCommandListener() do objeto que gerou o evento. No desenvolvimento de MIDlets comuns, cada objeto List implementa implicitamente (por meio da constante List.IMPLICIT passada no construtor da classe List) a interface javax.microedition.CommandListener. Sendo assim, o papel do controlador realizado por esta para gerenciar o fluxo da aplicao e redirecionar para o menu de acordo com a escolha do usurio. Essa abordagem s vivel quando a aplicao estiver usando poucas subclasses de List para representar as listas com itens de menus. Supondo que uma MIDlet simples em Java ME tivesse mais de 15 menus, alm de ser necessrio criar subclasses de List para cada menu, a gerncia do controle do fluxo entre os menus torna-se mais complexo e custoso. Uma implementao de estrutura semelhante a essa pode ser alcanada por meio do padro de

    projeto MVC (Model-View-Controller/Modelo-Viso-Controlador). Neste padro, ocorre o total desacoplamento das responsabilidades de cada parte da aplicao, sendo que o Modelo de dados responsvel pela representao das regras de negcio, a Viso renderiza o modelo de dados por meio de componentes de Interface Grfica com o Usurio (GUI Graphical User Interface, na verdade, em Java ME este termo pode ser substitudo por LCDUI Liquid Crystal Display User Interface que so componentes grficos de MIDP que foram projetados especificamente para serem visualizados por dispositivos com telas reduzidas) e o Controlador responsvel por capturar eventos gerados pelo usurio (que pode ser o clique de uma tecla de um dispositivo), gerenciar o fluxo da aplicao e controlar a conversa com o modelo e a viso. O modelo informa viso que os dados foram alterados e esta renderiza os dados com os valores atualizados. A arquitetura MVC mostrada na Figura 2. O padro Cascading Menu (ver Figura 3) pode ser considerado uma verso mvel do MVC.

    Sendo assim, o modelo de dados pode ser mantido e atualizado independente do tipo de viso que ser utilizada. Qualquer rearranjo no sistema de menus implicar apenas na reorganizao da estrutura do modelo representada por uma rvore de menus.

    Figura 2. A Arquitetura MVC. Pattern: Cascading Menu

  • 6/21

    Figura 3. Arquitetura do padro Cascading Menu. Objetivo Permitir criar uma hierarquia complexa de menus, de forma a abstrair o

    encadeamento entre telas. Problema Para implementao de uma hierarquia de menus com lista de itens,

    normalmente em MIDP, seria necessrio criar subclasses de List para cada menu a ser utilizado pela aplicao.

    Soluo A Arquitetura MVC para desacoplar a parte do Modelo da Viso por meio de um Controlador.

    Participantes MenuList: Responsvel pela visualizao da hierarquia de itens de menu. Realiza o papel da viso.

    List: Componente grfico de MIDP para representao de lista. MenuElement: Representa um elemento do menu, que pode ser um texto ou

    um outro menu aninhado. Representa o modelo. MDisplayable: Interface responsvel pela visualizao dos Displayables que

    desejam ser exibidos ao trmino da navegao dos menus. Displayable: Classe me de todos os componentes grficos de MIDP. CommandListener: Interface de MIDP que permite capturar eventos de

    comandos (clique em uma tecla do dispositivo, por exemplo). Realiza o papel do Controlador.

    Conseqncias Uma hierarquia de menus mais complexa, porm, novas adies de menus estrutura acontecem de modo mais simples.

    Implementao Vrios elementos de menus so criados e adicionados na hierarquia por meio do mtodo addChild() de MenuElement. Os Displayables que necessitem ser exibidos (de acordo com as opes de menus selecionadas) devem obrigatoriamente implementar o mtodo onDisplay() de MDisplayable. Depois, chama-se o mtodo showMenu() de MenuList para que a estrutura completa de menus seja visualizada.

    O exemplo para este padro ser um guia de informaes de cidades onde sero exibidos vrios menus. O usurio selecionar o que deseja (por exemplo, informaes sobre lazer, restaurantes, etc.) e conforme a opo escolhida, novos menus so apresentados de acordo com o filtro selecionado anteriormente. Ao trmino ser mostrado uma mensagem informando o item selecionado. A Figura 4 mostra a hierarquia de menus disponveis na aplicao.

    Figura 4. Hierarquia de menus no padro Cascading Menu. O componente MenuElement representa o modelo, que ser utilizado para criar a rvore de menus.

    Cada MenuElement representa um n (ou item do menu) da rvore de menus. Esses ns podem se

    Menu Principal

    Lojas Restaurantes Lazer

    Lojas Automveis Livros Moda

    Restaurantes Padarias Cafs Refeies

    Lazer Museus Galerias Espetculos

  • 7/21

    comportar tanto como um n-pai ou n-filho. Analisando a Listagem 2, podemos perceber que a relao de hierarquia realizada pelo mtodo addChild() que foi sobrecarregado e possui suas verses recebendo ambos dois parmetros: addChild(child,next_container), no qual child representa o item de menu que est sendo adicionado e next_container, o prximo MenuElement a ser exibido assim que o item do menu for selecionado (se selecionssemos o item de menu Lojas na tela do menu principal, a tela de lojas disponveis seria exibida em seguida); e addChild(child,display) onde display ser o Displayable que ser mostrado assim que child for selecionado. Esta classe possui o vetor children representando um container para MenuElements e o Hashtable menuMap, que far o mapeamento dos prximos itens de menu ou Displayables que sero exibidos. O mtodo commandAction() possui a regra de negcio para escolher o que ser visualizado assim que o item de menu for selecionado. Assim que o modelo criado, a classe MenuList, que uma especializao de uma List, renderiza os dados representados pelo modelo, realizando dessa forma o papel da camada de viso. A grande vantagem que MenuList pode ser reutilizada em aplicaes futuras, uma vez que a viso est totalmente desacoplada do modelo. A Listagem 3 representa este componente. O mtodo showMenu() de MenuList o responsvel por

    visualizar os dados do modelo. Ele possui um lao interno responsvel por recuperar todos os MenuElements salvos em children e visualiz-los. Mas primeiro ele chama o mtodo deleteAll(), sobrescrito de List, para remover quaisquer itens de menu que estejam sendo exibidos no momento. Porm, para que os dados possam ser exibidos assim que a navegao pelos menus terminar, as classes obrigatoriamente devem ser um Displayable. A Listagem 4 mostra a implementao de SampleMenuAction, que ser a classe que visualizar os

    dados retornados. No nosso exemplo, adotamos um carter mais didtico no qual o dado visualizado ser somente o nome do item de menu que o usurio selecionou. Porm, em uma aplicao mvel comercial, os dados poderiam ser resultado de uma pesquisa em um banco de dados armazenado em um servidor remoto ou da consulta utilizando um Web Service. A classe SampleMenuAction estende TextBox, que o componente de MIDP que permite entrada de textos longos, ocupando toda a tela do dispositivo. Basicamente, ela define seu construtor que chama o construtor de TextBox e so passados os parmetros, respectivamente, representando o ttulo, o texto, a quantidade mxima de caracteres e a restrio de entrada de texto, indicando que qualquer texto alfanumrico e com caracteres especiais pode ser inserido. Alm disso, ela implementa a interface MDisplayable (Listagem 5) e o mtodo onDisplay(), que chamado quando o usurio seleciona a opo de menu associada a um MDisplayable. A Listagem 6 descreve a MIDlet que utiliza os outros componentes participantes do padro

    Cascading Menu. Essencialmente, os MenuElements so instanciados e o mtodo addChild() de cada objeto chamado e configurado para poder construir a hierarquia de menus. Por fim, o mtodo showMenu() de MenuList chamado e passado como parmetro o objeto que representa o menu principal (varivel main).

    Padro Wizard Dialog Este padro de projeto tem como objetivo abstrair o desenvolvedor sobre o controle do fluxo de

    navegao entre as telas (que podem ser representados pelo componente Form do perfil MIDP), desacoplando as telas entre si e permitindo que nos preocupemos unicamente com a implementao do contedo de cada tela. Tal abstrao pode ser alcanada conjuntamente com outro padro de projeto, o Mediator, que permite que um componente intermedirio controle vrios outros componentes relacionados. No diagrama de classes apresentado na Figura 5, o componente WizardEngine (apresentado na

    Listagem 7) realiza o papel do mediador. Ele possui uma referncia para um vetor de telas de dilogo utilizadas na aplicao (representado pelo Vector dialogs), que pode ser qualquer subclasse direta ou indireta de WDialog (Listagem 8). Alm disso, a engine do padro possui os mtodos addDialog() (um detalhe interessante referente a este mtodo pode ser visto no quadro Curiosidade

  • 8/21

    no mtodo addDialog()) e startWizard() que, respectivamente, adiciona os dilogos no vetor e retorna o ndice da tela de dilogo que est sendo adicionada. Inicialmente, a classe WDialog que uma especializao de javax.microedition.lcdui.Form declara vrias flags que representam as aes de navegao (NEXT e BACK), a direo do fluxo da aplicao: avanando (FORWARD) ou retornando para a tela anterior (BACKWARD); e valores para serem retornados de acordo com a validao dos dados, se estes foram aceitos (OK) a prxima tela ser mostrada, caso contrrio (REJECT) a mudana de tela no acontecer enquanto os dados passados no forem vlidos. Continuando, o mtodo initByEngine() chama o mtodo abstrato initDialog() que o responsvel

    por inicializar todas as telas de dilogos, permitindo configurar os objetos grficos (como Commands, TextFields, ChoiceGroups, etc.) logo na inicializao de uma WDialog (subclasses desta). Ele deve ser implementado por todas as subclasses de WDialog (no nosso exemplo, WPage1, WPage2, WPage3 e WPage4). Esta classe possui tambm o mtodo onLeave() que realiza a validao dos dados assim que o fluxo da aplicao estiver entrando em uma tela; e o mtodo onEnter() que, analogamente a onLeave() tambm realiza a validao dos dados, porm, quando uma tela (representada por subclasses de WDialog) estiver prestes a ser exibida. A MIDlet que exemplifica este padro permite pesquisarmos informaes de cidades de acordo

    com algum critrio de busca. A aplicao possui quatro telas simples, que so representadas pelos componente WPage1 (Listagem 9), WPage2 (Listagem 10), WPage3 (Listagem 11) e WPage4 (Listagem 12). A primeira tela mostra apenas uma informao inicial indicando como o usurio deve prosseguir

    para a execuo da MIDlet. A segunda mostra uma lista de cidades disponveis para escolha (representada pelo componente ChoiceGroup). A terceira permite que um termo de busca seja informado de acordo com o filtro (a cidade) selecionado anteriormente. Caso este termo no seja informado, a engine trata de validar os dados por meio do mtodo sobrescrito onLeave() e exibe uma mensagem informando que o campo de pesquisa deve ser preenchido com no mnimo 3 caracteres, no permitindo que o fluxo da aplicao mude para outra tela enquanto o campo de busca no for preenchido. Caso a validao ocorra com sucesso, a quarta tela ser exibida. No nosso exemplo, para melhor entendimento, ela apenas ir mostrar o nome da cidade selecionada (Wizardlet.answer1) e o valor que foi informado no campo de pesquisa (Wizardlet.answer2). A Listagem 13 mostra a MIDlet utilizando os outros componentes do padro, na qual o mtodo addDialog() chamado e passados como parmetros os objetos das subclasses de WDialog. Ao trmino, chamado o mtodo startWizard() para iniciar a exibio das telas da aplicao.

    Curiosidade do mtodo addDialog() O mtodo addDialog() possui uma caracterstica no mnimo curiosa e que pode levar o leitor a

    pensar que o tratamento de eventos de pressionamento de teclas neste padro no ir funcionar corretamente: se voc perceber, WizardEngine possui a definio do mtodo commandAction() de javax.microedition.CommandListener porm no implementa esta interface! Em vez disso, ele chama o mtodo initByEngine() de WDialog que realmente implementa a interface de captura de comandos. Na verdade, WDialog desempenha tambm o papel de um Proxy para CommandListeners. Isto ocorre pois esta classe ir tratar somente eventos de comandos para ir para a prxima (varivel NEXT_COMMAND) ou tela anterior (varivel BACK_COMMAND) so capturados pelo CommandListener que ela implementa (representado pela chamada engine.commandAction() ), sendo que outros eventos gerados pelo usurio (eventos de confirmao, sair, etc) sero redirecionados para outros CommandListeners (representado pela chamada listener.commandAction()). Pattern: Wizard Dialog

  • 9/21

    Figura 5. Arquitetura do padro Wizard Dialog.

    Objetivo Focar o desenvolvimento da aplicao nos dialogs (que podem ser representados por Forms) em vez de se preocupar com a complexidade do encadeamento de telas.

    Problema Os dados que so passados entre telas podem ser passados de forma inconsistente, sem terem sido validados durante a mudana de telas da aplicao.

    Soluo A Arquitetura MVC utilizada para separar o modelo da viso por meio de um Controller.

    Participantes WDialog: Classe abstrata que permite executar mecanismos de inicializao dos seus componentes grficos, validar os dados antes de entrar ou depois de sair de uma tela (subclasses de WDialog).

    WizardEngine: Responsvel pelo gerenciamento do fluxo entre as telas do sistema.

    WPage1, WPage2, Wpage3, WPageN: Subclasses de WDialog que representam as telas da aplicao.

    Form: Classe de MIDP para representar formulrios. Conseqncias As telas da aplicao podem ser desenvolvidos de maneira independente,

    facilitando a validao dos dados passados entre telas. Implementao Subclasses de WDialog sobrescrevem os mtodos onEnter(), onLeave() para

    validao dos dados de acordo com o fluxo da aplicao (entrando ou saindo de um Form) e implementam o mtodo initDialog() para permitir a inicializao dos componentes grficos. Depois, WizardEngine responsvel pela exibio das telas.

    Padro Pagination Devido aos dispositivos mveis possurem uma tela limitada, a disposio dos objetos de texto

    reduzida a aproximadamente 10 linhas (dependendo do tamanho da tela do dispositivo), dificultando a navegao, visualizao e legibilidade do contedo. Devido a esta limitao, torna-se necessrio o uso de mtodos que paginem o texto, seja por barra de rolagem ou por menus: avanar e voltar. O padro Pagination visa contornar este problema por meio da utilizao do componente PagableList. Este padro permite que uma lista de elementos seja dividida em pginas menores para melhorar a

    visibilidade e navegabilidade dos dados apresentados, sendo utilizado para isso outro padro de projeto, chamado Proxy, que utilizado quando devem existir vrias cpias de um objeto complexo, porm s vezes o processo de cpia pode requerer um espao significativo na memria, o que conseqentemente causa uma perda no desempenho da aplicao. Nessa ocasio, outro objeto (proxy) instanciado em vez de ocorrer diretamente a instanciao do objeto real. Para minimizar o carregamento dos dados, o padro utiliza outro padro, chamado de Flyweight. Ele fundamental

  • 10/21

    no padro Pagination, pois, h muitos objetos (os itens da lista) e estes precisam ser carregados de forma a no ocupar muita memria durante este processamento. Sendo assim, este processo deve ocorrer por demanda, ou seja, somente quando necessrio. Na Figura 6 vemos a arquitetura do padro Pagination. Para exemplificar a facilidade na seleo e leitura dos itens na lista, realizado um comparativo de

    como uma mesma aplicao executada no emulador sem (Figura 7) ou com (Figura 8) a utilizao deste padro. Na Figura 7, percebemos claramente um inchao visual na MIDlet. Caso o usurio necessite acessar, por exemplo, o item na posio 45 de uma lista de 50 itens, preciso que o mesmo navegue incessantemente pelos elementos at alcanar o item desejado. J na Figura 8, vemos uma MIDlet mais enxuta, com menos itens por pgina, sendo possvel avanar na paginao, representado pelo comando More, ou recuar, se selecionarmos o comando Prev. Na Listagem 14, percebemos que a classe PagableList possui mtodos chamados showPrevPage() e

    showNextPage(). Estes mtodos so centrais no padro Pagination, pois acionam respectivamente a pgina anterior e posterior, facilitando sua navegabilidade e proporcionando maior conforto visual ao usurio, haja vista que no sero exibidas telas carregadas de textos (mais de 20 itens, por exemplo) ou figuras, o que normalmente necessita de uma parte considervel de memria do dispositivo para que a lista seja renderizada. Alm disso, temos o mtodo utilitrio updateList(), que atualiza os itens da lista e os mtodos sobrescritos da classe List (existem outros mtodos de List que foram sobrescritos, entretanto, foram omitidos na listagem por questes de espao), que so append(), delete(), insert() que respectivamente adiciona cada texto do item e sua imagem (opcional) nos vetores que os representam (allStrings e allImages), deleta e insere o texto ou imagem do item da lista nos vetores de acordo com sua posio. Na Listagem 15, a MIDlet representando este padro, inicialmente instancia um objeto PagableList. Depois, dentro do mtodo startApp(), o lao adiciona um nmero significativo de itens no objeto (100 itens) PagableList para colocar o padro Pagination em funcionamento. Pattern: Pagination

    Figura 6. Arquitetura do padro Pagination.

    Objetivo Permitir que uma lista consideravelmente grande de itens seja divida em pginas menores.

    Problema Uma lista pode conter um nmero muito grande de itens que na maioria das vezes torna cansativa a navegabilidade.

    Soluo Particionar uma lista grande de itens em pginas menores, facilitando a visualizao dos mesmos e evitar a sobrecarga da memria do dispositivo carregando as pginas menores de cada vez, por demanda.

    Participantes PagableList: Representa cada pgina da lista. List: Componente grfico de MIDP para representao de lista de itens.

    Conseqncias Uma MIDlet com mais listas, porm, cada uma com menos itens sendo mostrados por pgina. Com isso, no ocorre sobrecarga da memria do

  • 11/21

    dispositivo, pois cada pgina carregada por demanda. Implementao Cada PagableList possui mecanismos para visualizao do prximo (mtodo

    showNextPage()) ou da pgina anterior (mtodo showPrevPage()); e pode, opcionalmente, definir o nmero de itens que devem ser exibidos por pgina.

    Figura 7. Exemplo de uma aplicao que no utiliza Pagination.

  • 12/21

    Figura 8. Aplicao usando o padro Pagination.

    Padro Slide Show Outro problema a ser resolvido refere-se apresentao de telas (slides) e o tempo entre elas nos

    dispositivos mveis, como uma apresentao em um editor de slides. O padro Slide Show prope a utilizao da classe Displayable (classe me dos componentes grficos) da especificao MIDP para solucionar este problema. Para a utilizao deste padro, todos os Displayables so criados igualmente apenas mudando seu

    contedo (texto, imagem ou algum dado personalizado pelo desenvolvedor). Assim, se atribui a responsabilidade da apresentao dos slides e a passagem dos mesmos baseando-se em uma espera de tempo pr-definida no componente SlideEngine, deixando com isso o programador livre da implementao da mudana de slides e seu tempo, melhorando o desempenho do aplicativo e diminuindo a complexidade do cdigo. Alguns exemplos de aplicao deste padro so os helps de games que descrevem passo-a-passo, como um tutorial, como realizar cada funcionalidade do jogo (comandos de navegao, regras de pontuao, etc.). Pela Figura 9, podemos observar a estrutura deste padro. Analogamente ao padro Pagination visto anteriormente, temos os mtodos startShow() e

    endShow() na classe SlideEngine (Listagem 16). Tais mtodos permitem o incio e o trmino da apresentao dos slides, respectivamente. Podemos visualizar tambm nesta listagem o mtodo addSlide(), responsvel pela adio dos slides. Ele recebe dois parmetros: um Displayable, que ser o componente grfico a ser exibido e um inteiro, representando o tempo de espera entre o prximo slide. Para melhorar o gerenciamento da durao, temos a classe Timer que implementa Runnable para representar um contador para o prximo slide. Finalmente, chamando o mtodo startShow() iniciamos a exibio dos slides. A Listagem 17 mostra a MIDlet necessria para exemplificar este padro, na qual os slides (objetos da classe Form) vo sendo criados e ao trmino, adicionados na engine por meio do mtodo addSlide() e iniciada a execuo por meio do mtodo startShow().

  • 13/21 Pattern: Slide Show

    Figura 9. Arquitetura do padro Slide Show.

    Objetivo Permitir que a transio entre telas da aplicao seja realizada de maneira automtica de acordo com determinado intervalo de tempo.

    Problema A necessidade de pressionar sempre o comando para ir para a prxima tela pode se tornar um tanto quanto tediosa. Em determinados casos, por exemplo, em helps da aplicao ou em slides de imagens, vivel definir uma durao para a transio entre telas.

    Soluo Definir uma durao entre telas para que a transio seja realizada de maneira automtica.

    Participantes SlideEngine: Responsvel por adicionar a durao entre os slides e gerenciar o fluxo da aplicao.

    Displayable: Classe de MIDP que representa qualquer elemento grfico que pode ser exibido na tela do dispositivo.

    Screen: Classe me dos componentes grficos que podem ser mostrados na tela do dispositivo.

    Canvas: Classe que representa uma tela simples que possui recursos para desenho (muito usada para construo de jogos).

    TextBox: Componente em MIDP que permite entrada de textos extensos. Form: Classe de MIDP que representa formulrios.

    Conseqncias No necessrio o usurio pressionar nenhum comando para mudar de um slide para outro.

    Implementao Subclasses de Screen ou Canvas devem ser criadas e adicionadas por meio do mtodo addSlide() de SlideEngine, possibilitando a transio automtica das telas da aplicao de acordo com o tempo de durao fornecido.

    Frameworks em Java ME A utilizao massiva de padres de projetos na plataforma Java ME tem proporcionado o desenvolvimento de frameworks (alguns open sources e outros comerciais) que permitem criar aplicaes mveis mais complexas e robustas. Alguns exemplos so o Floggy (www.floggy.org) projeto verde e amarelo que implementa a idia de persistncia no modelo objeto-relacional e o J2ME Polish (www.j2mepolish.org), que alm de ser um framework que incrementa vrios aspectos em Java ME, como novos widgets, servios de log, serializao de objetos, desenvolvimento de GUIs baseadas em CSS (Cascading Style Sheet) e outros, possui integrao com IDEs conhecidas, como o Eclipse, Netbeans, IntelliJ e permite, por meio de diretivas de pr-processamento, que uma nica aplicao seja desenvolvida para vrias famlias de dispositivos, diminuindo com isso o problema da fragmentao. Este framework possui uma verso livre, mais restrita em funcionalidades, e outra verso comercial que possui todas as novidades disponveis no framework.

  • 14/21

    Percebemos que apesar do desenvolvimento de framework em Java ME ser restrito, devido plataforma ainda no suportar recursos mais complexos como reflexo (tambm chamado de introspeco), vrias empresas e pesquisadores vm criando frameworks que abrangem diversos domnios, a exemplo os frameworks Floggy e J2ME Polish citados anteriormente (recomendo o leitor a realizar uma pesquisa em sites de hospedagens de projetos Open Source, como SourceForge.net, Google Code, etc. para analisar a quantidade significativa de frameworks desenvolvidos para Java ME). Ns desenvolvedores esperamos ansiosamente por novas JSRs para as verses da configurao CLDC 1.1 e perfil MIDP 2.0 ou um incremento da verso mvel de Java (a to aguardada MIDP 3.0) que suporte tais recursos citados anteriormente, o que conseqentemente iria tornar a plataforma uma das mais promissoras para desenvolvimento de aplicaes comerciais mveis.

    Concluses Este artigo mostrou a viabilidade de se aplicar padres de projetos em aplicaes mveis para Java

    ME, sendo descritos, por meio de exemplos prticos, quatro padres: Cascading Menu, Wizard Dialog, Pagination e Slide Show, que solucionam problemas comumente enfrentados por ns durante a composio de GUIs para dispositivos MIDP. A criao de um padro de projeto, na maioria das vezes, implica na utilizao de duas ou mais

    classes abstratas e interfaces. Por isso, caso a aplicao utilize muitos padres de projeto, a conseqncia disso pode ser uma MIDlet pesada e lenta, o que acabaria diminuindo o desempenho do dispositivo. Entretanto, isso no significa que a utilizao de mais de um padro de projeto se torne invivel para as aplicaes (por exemplo, a MIDlet Suite com os quatro padres de projetos que foram utilizados neste artigo ficou com um tamanho aproximado de 12 Kb sem utilizar um obfuscador). Nesse caso, determinado padro pode sofrer uma leve adaptao para se comportar bem ao ambiente mvel, porm sem perder as suas caractersticas. At o prximo artigo!

    Ramon Ribeiro Rabello ([email protected]) desenvolvedor Java h 4 anos, tendo experincia nas trs especificaes:JSE, JEE e JME. J trabalhou em projetos de aplicaes mveis e servios M-Payment. Publicou artigos sobre plataformas mveis e atualmente cursa Mestrado pela Universidade Federal de Pernambuco (UFPE) em Engenharia de Software.

    Pedro J. F. Treccani ([email protected]) desenvolvedor Java h 4 anos, com experincia nas trs especificaes de Java. J trabalhou no desenvolvimento de projetos integrando aplicaes mveis com Sistemas Integrados de Gesto Empresarial(SIGE),servios M-Commerce e E-Commerce. Publicou artigos sobre plataformas mveis, cursando atualmente Mestrado como aluno especial pela Universidade Federal de Par (UFPA) em Engenharia de Software.

  • 15/21

    Thienne Johnson ([email protected]) professora da Unama, com mestrado (UFSCar) e Doutorado (UFPE) em Cincia da Computao. Atualmente faz ps-doutorado na Faculdade de Engenharia Eltrica e de Computao na Unicamp. autora do livro Java para Dispositivos Mveis Desenvolvendo Aplicaes com J2ME, da editora Novatec.

    Links javaworld.com/javaworld/jw-12-2002/jw-1213-j2medesign.html Sobre os quatro padres de projetos. eclipse.org/ganymede Site da IDE Eclipse Ganymede. eclipseme.org Site do EclipseME. http://www.ibm.com/developerworks/library/wi-arch22/ O Padro de Projeto Factory em MIDP 2.0.

    Listagem 2. Implementao do componente MenuElement: MenuElement.java public class MenuElement implements CommandListener { public Vector children = new Vector(); Hashtable menuMap = new Hashtable(); public String text; // construtor e outros mtodos utilitrios // adiciona um item de menu e liga ao prximo container public void addChild(MenuElement child, MenuElement next_container) { children.addElement(child); menuMap.put(child, next_container); } // adiciona um item de menu e liga ao prximo componente grfico public void addChild(MenuElement child, Displayable display) { children.addElement(child); menuMap.put(child, display); } public void commandAction(Command command, Displayable displayable) { if (command.equals(List.SELECT_COMMAND) && displayable instanceof MenuList){ MenuList list = (MenuList) displayable; int i = list.getSelectedIndex(); MenuElement item = (MenuElement) children.elementAt(i); Object next = menuMap.get(item); if (next instanceof MenuElement) list.showMenu((MenuElement) next); else if (next instanceof MDisplayable && next instanceof Displayable) { ((MDisplayable) next).onDisplay(item); list.getDisplay().setCurrent((Displayable) next); } else if (next instanceof Displayable) list.getDisplay().setCurrent((Displayable) next); } } }

    Listagem 3. Implementao do componente MenuList: MenuList.java public class MenuList extends List { Display display = null; public void showMenu(MenuElement menu) { deleteAll(); // sobrescreve deleteAll() de List display.setCurrent(this); for (int i = 0; i < menu.children.size(); i++) { MenuElement item = (MenuElement) menu.children.elementAt(i); append(item.text, null); }

  • 16/21

    this.setTitle(menu.text); setCommandListener(menu); } } Listagem 4. TextBox representando os dados retornados pela navegao: SampleMenuAction.java public class SampleMenuAction extends TextBox implements MDisplayable { public SampleMenuAction() { super("Action", "Contedo", 40, TextField.ANY); } public void onDisplay(MenuElement e) { this.setString("Voc selecionou o item" + e.text); } }

    Listagem 5. Implementao do componente MDisplayable: MDisplayable.java public interface MDisplayable { public void onDisplay( MenuElement e ); } Listagem 6. MIDlet que utiliza o padro Cascanding Menu: Menulet.java public class Menulet extends MIDlet { static Menulet instance; MenuList menulist = null; public void startApp() { menulist = new MenuList(Display.getDisplay(this)); MenuElement menu3 = new MenuElement("Lazer"); menu3.addChild(new MenuElement("Museu"), new SampleMenuAction()); menu3.addChild(new MenuElement("Galeria"), new SampleMenuAction()); menu3.addChild(new MenuElement("Espetculos"), new SampleMenuAction()); // a mesma idia para menu2 e menu1 MenuElement main = new MenuElement("Menu"); main.addChild(new MenuElement("Lojas"), menu1); main.addChild(new MenuElement("Restaurantes"), menu2); main.addChild(new MenuElement("Lazer"), menu3); menulist.showMenu(main); } } Listagem 7. Criando os WDialogs com WizardEngine: WizardEngine.java public class WizardEngine { Display display = null; Vector dialogs = new Vector(); public int addDialog(WDialog dialog) { dialogs.addElement(dialog); dialog.initByEngine(this); return dialogs.size() - 1; } // inicia mostrando o primeiro dialog no Vector public void startWizard() { if (dialogs.size() > 0) { WDialog dialog = (WDialog) dialogs.elementAt(0); display.setCurrent(dialog); } } public void commandAction(Command command, Displayable displayable) { WDialog cur_dialog = (WDialog) displayable; if (command == WDialog.NEXT_COMMAND) { int i1 = dialogs.indexOf(displayable); if (i1 < dialogs.size() - 1) { WDialog next_dialog = (WDialog) dialogs.elementAt(i1 + 1); if (cur_dialog.onLeave(WDialog.FORWARD) != WDialog.OK) return; if (next_dialog.onEnter(WDialog.FORWARD) != WDialog.OK) return; display.setCurrent(next_dialog); } } else if (command == WDialog.BACK_COMMAND) { int i1 = dialogs.indexOf(displayable); if (i1 > 0) {

  • 17/21

    WDialog prev_dialog = (WDialog) dialogs.elementAt(i1 - 1); if (cur_dialog.onLeave(WDialog.BACKWARD) != WDialog.OK) return; if (prev_dialog.onEnter(WDialog.BACKWARD) != WDialog.OK) return; display.setCurrent(prev_dialog); } } } } Listagem 8. Representando um WizardDialog em cdigo: WizardDialog.java public abstract class WDialog extends Form implements CommandListener { public final static int NEXT = -1; public final static int BACK = -2; // parmetros para onEnter() e onLeave() public final static int FORWARD = -3; public final static int BACKWARD = -4; // valores de retorno para onEnter() e onLeave() public final static int OK = -5; public final static int REJECT = -6; public final static Command NEXT_COMMAND = new Command("NEXT", Command.OK, 1); public final static Command BACK_COMMAND = new Command("BACK", Command.BACK, 1); // declarao de CommandListener e WizardEngine public void initByEngine(WizardEngine e) { initDialog(); // Cada wizard dialog deve conter commandos de Next e Back // Uma melhor soluo dever exibir somente um comando de Next // no primeiro dialog e somente um Back na ltima dialog. // Fica como exerccio adicional aos leitores addCommand(NEXT_COMMAND); addCommand(BACK_COMMAND); this.engine = e; super.setCommandListener(this); } public int onEnter(int dir) { return OK; } public int onLeave(int dir) { return OK; } public void commandAction(Command command, Displayable displayable) { if (command == NEXT_COMMAND || command == BACK_COMMAND) engine.commandAction(command, displayable); else if (listener != null) listener.commandAction(command, displayable); } public abstract void initDialog(); }

    Listagem 9. Primeira tela a ser mostrada: WPage1.java public class WPage1 extends WDialog { public void initDialog() { setTitle("Passo 1"); append("Introduo: Pressione NEXT em cada pgina para avanar"); } }

    Listagem 10. Segunda tela a ser mostrada: WPage2.java public class WPage2 extends WDialog { public void initDialog() { setTitle("Passo 2"); question1 = new ChoiceGroup("Selecione a cidade que deseja obter informaes:", ChoiceGroup.EXCLUSIVE, new String[] { "Belm", "Recife", "Rio", So Paulo }, null); append(question1); } public int onLeave(int dir) { if (dir == WDialog.FORWARD) { int idx = question1.getSelectedIndex(); if (idx == -1) return WDialog.REJECT; else { String answer = question1.getString(idx); Wizardlet.answer1 = answer; return OK;

  • 18/21

    } } else return OK; } }

    Listagem 11. Terceira tela a ser mostrada: WPage3.java public class WPage3 extends WDialog { public void initDialog() { setTitle("Step 3"); question2 = new TextField("Entre com o termo de busca", null, 40, TextField.ANY); append(question2); } public int onLeave(int dir) { if (dir == WDialog.FORWARD) { String answer = question2.getString(); if (answer.length() < 3) { Alert alert = new Alert("Erro de Entrada"); alert.setString("Voc deve digitar pelo menos 3 caracteres"); super.engine.getDisplay().setCurrent(alert, this); return WDialog.REJECT; } else { Wizardlet.answer2 = answer; return WDialog.OK; } } else return OK; }

    } Listagem 12. Quarta tela mostrando o resultado: WPage4.java public class WPage4 extends WDialog { StringItem text; public WPage4() {} public void initDialog() { setTitle("Passo 4"); text = new StringItem(null, null); append(text); } public int onEnter(int dir) { // retorna os valores da tela anterior e os exibem text.setText("Voc selecionou " + Wizardlet.answer1 + " e digitou o valor " + Wizardlet.answer2 + " como critrio de busca. Este o fim deste Wizard demo."); return WDialog.OK; } } Listagem 13. MIDlet que utiliza o padro Wizard Dialog: Wizardlet.java public class Wizardlet extends MIDlet { // declarao de variveis e construtor public void startApp() { engine = new WizardEngine(Display.getDisplay(this)); engine.addDialog(new WPage1()); engine.addDialog(new WPage2()); engine.addDialog(new WPage3()); engine.addDialog(new WPage4()); engine.startWizard(); } } Listagem 14. Elementos que podem ser paginados: PagableList.java public class PagableList extends List { public final static Object DUMMY = new Object(); public final static Command MORE_COMMAND = new Command("More", Command.SCREEN, 1); public final static Command PREV_COMMAND = new Command("Prev", Command.SCREEN, 1); Vector allStrings = new Vector(100); Vector allImages = new Vector(100);

  • 19/21

    int maxItem = 4; // s um default int curItem = 0; CommandListener listener = null; public PagableList(String title, int listType) { super(title, listType); addCommand(MORE_COMMAND); addCommand(PREV_COMMAND); super.setCommandListener(new CommandAction()); } public PagableList(String title, int listType, String[] stringElements, Image[] imageElements) { super(title, listType); addCommand(MORE_COMMAND); addCommand(PREV_COMMAND); super.setCommandListener(new CommandAction()); } private void updateList() { int s = super.size(); for (int i = 0; i < s; i++) { super.delete(0); } for (int i = curItem; i < curItem + maxItem; i++) { // se i exceder o ltimo ndice de allStrings, ento sai do lao if (!(i < allStrings.size())) break; String a_item = (String) allStrings.elementAt(i); Image img = null; Object obj = allImages.elementAt(i); if (obj == DUMMY) img = null; else img = (Image) obj; super.append(a_item, img); } } public void showPrevPage() { int last = allStrings.size() - 1; if (curItem - maxItem >= 0) { curItem -= maxItem; updateList(); } } public void showNextPage() { int last = allStrings.size() - 1; if (curItem + maxItem = allStrings.size()) throw new IndexOutOfBoundsException(); allStrings.removeElementAt(elementNum); allImages.removeElementAt(elementNum); // if affected element is currently showing, then refresh the list if (elementNum >= curItem && elementNum < curItem + maxItem) updateList();

  • 20/21

    } public void insert(int elementNum, String stringPart, Image imagePart) { if (elementNum >= allStrings.size()) throw new IndexOutOfBoundsException(); if (stringPart == null) throw new NullPointerException(); if (imagePart != null && imagePart.isMutable()) throw new IllegalArgumentException(); allStrings.insertElementAt(stringPart, elementNum); if (imagePart != null) allImages.insertElementAt(imagePart, elementNum); else allImages.insertElementAt(DUMMY, elementNum); if (elementNum >= curItem && elementNum < curItem + maxItem) updateList(); } private class CommandAction implements CommandListener { public void commandAction(Command command, Displayable displayable) { if (command == MORE_COMMAND) showNextPage(); else if (command == PREV_COMMAND) showPrevPage(); else if (listener != null) listener.commandAction(command, displayable); } } }

    Listagem 15. MIDlet que utiliza o padro Pagination: Paginglet.java public class Paginglet extends MIDlet{ static Paginglet instance; PagableList pagablelist = new PagableList( "Paging", List.IMPLICIT); public Paginglet() { instance = this; } public void startApp() { Display.getDisplay(this).setCurrent(pagablelist); for ( int i=0; i< 100; i++ ) pagablelist.append( "Item #"+i, null ); } }

    Listagem 16. Classe que configura os slides e durao das transies: SlideEngine.java public class SlideEngine { Display display; Vector sequence; // Conter a seqncia de slides Thread thread; Timer timer; public SlideEngine(Display d) { display = d; sequence = new Vector(); } public void addSlide(Displayable slide, int t) { sequence.addElement(slide); sequence.addElement(new Integer(t)); } public void startShow() { timer = new Timer(); thread = new Thread(timer); thread.start(); } public void endShow() { timer.done = true; } class Timer implements Runnable { int time; boolean done; public void run() { done = false; int cur = 0; // ndice da seqncia while (!done && cur < sequence.size()) {

  • 21/21

    Object o = sequence.elementAt(cur); System.out.println("sequence: " + o); if (o instanceof Displayable) { Displayable d = (Displayable) o; display.setCurrent(d); } else if (o instanceof Integer) { time = ((Integer) o).intValue(); try { Thread.sleep(time); } catch (Exception e) {} } cur++; // avana para o prximo slide } } } } Listagem 17. MIDlet que utiliza o padro Slide Show: Slidelet.java public class Slidelet extends MIDlet { static Slidelet instance; SlideEngine engine = null; public Slidelet() { instance = this; } public void startApp() { engine = new SlideEngine(Display.getDisplay(this); Form f1 = new Form("Slide 1"); f1.append("Este o slide 1"); // semelhante para f2 e f3 // adiciona os slides na engine, // com a durao de 2 segundos de transio engine.addSlide(f1, 2000); engine.addSlide(f2, 2000); engine.addSlide(f3, 2000); // inicia a exibio dos slides engine.startShow(); } }