Skip to content

Effetti “AJAX” con Java Micro Edition – parte 1

February 16, 2010

Molti sviluppatori, negli ultimi anni, si sono ritrovati ad affrontare le sfide poste dall’evoluzione delle interfacce utente in un numero crescente di dispositivi mobili. L’avvento di nuovi sistemi operativi, si pensi ad iPhone OS o ad Android, e di browser con funzionalità paragonabili a quelli dei PC, ha reso necessario lo sviluppo di nuove tecnologie che permettano alle applicazioni Java ME di reggere la competizione con l’arrembante concorrenza.

L’interminabile processo di formalizzazione di MIDP 3.0 e la scarsissima adozione su dispositivi reali del pur lodevole Java FX hanno però costretto gli sviluppatori a trovare una serie di soluzioni alternative, spesso consistenti in uno sfruttamento estremo dell’infrastruttura grafica a basso livello del “vecchio” MIDP 2.x.

Usando con accortezza le possibilità offerte dalle ridotte API del MIDP 2 è possibile implementare animazioni ed effetti simili a quelli Ajax. In questo post mostreremo alcuni accorgimenti che facilitano la scrittura di una funzionalità “AJAX” simile a quello usata da Google per suggerire termini di ricerca man mano che si scrive in un campo testo. L’implementazione di un client mobile dotato di una UI completamente customizzata è un lavoro lungo e di una certa complessità: in questo articolo forniremo solo le nozioni basilari per affrontare questa problematica.

Il modello applicativo di Ajax è di tipo asincrono; le richieste al server vengono eseguite da un modulo separato da quello che gestisce il disegno della UI, la quale viene modificata in tempo reale per adattarsi ai dati che giungono dalle response.

Modello applicativo Ajax
(fonte: J.J.Garrett from adaptivepath.com)

In Java ME, uno dei modi per ottenere delle UI personalizzate, più gradevoli e facili da usare rispetto a  quelle standard fornite dal sistema operativo del dispositivo è di creare componenti ed animazioni basati sulle classi Canvas e Graphics.

La classe Canvas è la “tela” su cui disegnare i nostri componenti tramite la giustapposizione di elementi geometrici come linee, poligoni e testo aggiunti con i metodi invocati su Graphics. Ad esempio, se g è la nostra istanza di Graphics:

String text = "Fortza Paris";
g.setColor(0xffffff);
g.fillRect(0, 0, Canvas.getWidth(), Canvas.getHeight());
g.setColor(0x000000);
g.drawRect(0, 0, Canvas.getWidth(), Canvas.getHeight());
g.drawString(text, Canvas.getWidth()/2, Canvas.getHeight()/2, Graphics.TOP|Graphics.HCENTER);

il codice soprastante disegna un rettangolo bianco con bordo nero grande quanto lo schermo, al cui centro si trova la stringa text. La UI appena disegnata viene tenuta in un buffer finchè non viene invocato un metodo di “esecuzione” del disegno come paint(), repaint() o serviceRepaints().

Vediamo ora come ottenere un comportamento simile a quello di Ajax in un’applicazione Java ME usando Canvas.

Creiamo una sottoclasse di Canvas (o, se necessario, di GameCanvas) che implementa Runnable, nel cui run() scriveremo il codice che ci permette un refresh ciclico dello schermo, utile per gestire transizioni, animazioni ed eventi della UI (come il cambio di focus da un elemento all’altro). L’esecuzione della UI in un thread separato, inoltre, ci permette di disaccoppiarla dal flusso base dell’applicazione e da altre operazioni potenzialmente bloccanti (es: connessioni).

final public void run(){
[...]
// “Invita” a ridisegnare lo schermo con le relative modifiche grafiche.
repaint(0, 0, width, height);
// Obbliga ad eseguire immediatamente qualunque richiesta di repaint ancora in attesa.
// Attenzione: è bloccante.
serviceRepaints();
[...]
}

Il codice del run() può inoltre comprendere una gestione del framerate (un refresh velocissimo potrebbe risultare troppo dispendioso per alcuni dispositivi, oltre che poco utile) e un metodo per la gestione centralizzata degli eventi, altro aspetto che, usando la Canvas, è gestito a basso livello andando ad intercettare gli eventi base sui tasti/schermo del cellulare.

Una volta scritta la parte che disegna la UI e gestisce i suoi eventi, è necessario scrivere la parte che si connette al server per richiedere i “suggerimenti” da mostrare a video.

Anche in questo caso, come dettano le norme di buona programmazione per applicazioni mobili, creeremo la classe che fa da client HTTP in modo che implementi Runnable, così da poter essere utilizzata in un thread separato e non bloccare la UI dell’applicazione.

Ipotizzando di effettuare delle richieste GET allo stesso server, il run() del nostro client, farà una cosa del genere:

synchronized (this){
		 // Se non vi sono richieste pendenti si aspetta...
                while (queryStrings.size() == 0){
                    try{
                        wait();
                    } catch (InterruptedException e){   }
                    //[...]
                }

                request = (String)(queryStrings.elementAt(0));
                listener = (ConnectionListener)listeners.elementAt(0);
		//[...]
            }
            sendRequest(request, listener);

il vettore listener è un registro di tutte le classi che richiedono una connessione, le cui queryString sono accodate nell’omonimo vettore e inoltrate progressivamente.

Il metodo sendRequest(request, listener) effettua le connessioni HTTP vere e proprie secondo la modalità standard del Generic Connection Framework di Java ME ed invoca il metodo di callback definito da un’interfaccia implementata dalle classi accodate in listener.

Di questa interfaccia e della gestione della response XML parleremo nella seconda parte di questo post.

Autore: Andrea Castello

Advertisements
No comments yet

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: