Você está na página 1de 21

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 MCommerce 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.
Para implementao de uma hierarquia de menus com lista de itens,
Problema
normalmente em MIDP, seria necessrio criar subclasses de List para cada
menu a ser utilizado pela aplicao.
A Arquitetura MVC para desacoplar a parte do Modelo da Viso por meio de
Soluo
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.
Vrios elementos de menus so criados e adicionados na hierarquia por meio
Implementao
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.
Menu Principal

Lojas

Lojas
Restaurantes
Lazer

Automveis
Livros
Moda

Restaurantes
Padarias
Cafs
Refeies

Lazer
Museus
Galerias
Espetculos

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

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.
Os dados que so passados entre telas podem ser passados de forma
Problema
inconsistente, sem terem sido validados durante a mudana de telas da
aplicao.
A Arquitetura MVC utilizada para separar o modelo da viso por meio de
Soluo
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.
Uma lista pode conter um nmero muito grande de itens que na maioria das
Problema
vezes torna cansativa a navegabilidade.
Particionar uma lista grande de itens em pginas menores, facilitando a
Soluo
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
Implementao

dispositivo, pois cada pgina carregada por demanda.


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.
A necessidade de pressionar sempre o comando para ir para a prxima tela
Problema
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.
Definir uma durao entre telas para que a transio seja realizada de maneira
Soluo
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 (ramon.rabello@gmail.com) 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 (pedrotreccani@gmail.com) 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 (thienne@ieee.org) 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 <= last) {
curItem += maxItem;
updateList();
}
}
public int append(String stringPart, Image imagePart) {
if (stringPart == null) throw new NullPointerException();
if (imagePart != null && imagePart.isMutable()) throw new IllegalArgumentException();
allStrings.addElement(stringPart);
if (imagePart != null)
allImages.addElement(imagePart);
else allImages.addElement(DUMMY);
int last = allStrings.size() - 1;
if (last < curItem + maxItem) super.append(stringPart, imagePart);
return last;
}
public void delete(int elementNum) throws IndexOutOfBoundsException {
if (elementNum >= 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();
}
}

Você também pode gostar