sabato 31 maggio 2014
domenica 25 maggio 2014
Utilizzare i Service in Android
Un componente di fondamentale importanza nell’architettura
Android è il Service. Esso è distinto dall’Activity, in quanto non necessita di
una UI, avendo il compito di restare in esecuzione in background a prescindere
dall’interfaccia grafica. Un componente (ad esempio una Activity), potrà
connettersi ad un particolare servizio con l’obiettivo di avviarlo o fermarlo.
Un esempio di servizio può essere un lettore musicale.
giovedì 22 maggio 2014
L'UML in pillole: Diagramma degli oggetti
Il linguaggio di modellazione UML nella sua ultima versione
2.0 comprende un numero di diagrammi pari a tredici, divisi in tre categorie:
- Structure Diagrams (strutturale) Class Diagram, Object Diagram, Component Diagram, Composite Structure Diagram, Package Diagram, e Deployment Diagram.
- Behavior Diagrams (comportamentale) Use Case Diagram (used by some methodologies during requirements gathering); Activity Diagram, e State Machine Diagram.
- Interaction Diagrams (dinamica) Sequence Diagram, Communication Diagram, Timing Diagram, e Interaction Overview Diagram.
In questo articolo, si farà una piccola trattazione di un solo diagramma: l’Object
Diagram.
Rendere un server MySQL accessibile da remoto
Problema:
Quando si installa un server MySQL sul proprio pc, per chiari motivi di sicurezza, qualsiasi connessione sulla porta 3306 viene rifiutata se non arriva da localhost (127.0.0.1). Come si può configurare MySQL in modo da accettare connessioni da remoto?
Soluzione
Quando si installa un server MySQL sul proprio pc, per chiari motivi di sicurezza, qualsiasi connessione sulla porta 3306 viene rifiutata se non arriva da localhost (127.0.0.1). Come si può configurare MySQL in modo da accettare connessioni da remoto?
Soluzione
mercoledì 21 maggio 2014
Estrarre il testo semplice dal codice HTML in Java
Problema
Si ha dell'HTML in una stringa Java e si vuole estrarre il testo semplice escludendo il codice HTML.
Soluzione
martedì 20 maggio 2014
Una galleria di foto collegata con una pagina di Facebook in PHP
La realizzazione di una galleria foto collegata con una pagina di Facebook in un sito realizzato in PHP ha numerosi vantaggi:
- Non si ha la necessità di realizzare nessuna pagina riservata dove predisporre il caricamento di foto
- Le foto hanno una visibilità in un social network di rilievo
- Possibilità di includere elementi social come i "Mi Piace" insieme agli eventuali commenti, etc
- Gestione delle foto centralizzata su Facebook e sincronizzata in maniera automatica
- Non si deve avere uno spazio web dove salvare le proprie foto
Per sfruttare questi enormi vantaggi è sufficiente effettuare delle operazioni preliminari sulla propria pagina Facebook rendendola accessibile dall'esterno solo per l'applicazione che si sta realizzando.
Recuperare il codice seriale di Windows
Solitamente il codice seriale del sistema operativo acquistato
insieme al PC si trova su una etichetta attaccata sulla scocca del proprio PC,
nella parte inferiore. Tuttavia, può succedere di non avere questa etichetta o
addirittura di rovinarla abbastanza da rendere il codice illegibile.
domenica 18 maggio 2014
Upload di foto su un album di una pagina Facebook in PHP
Si vuole realizzare una pagina in php dove l’utente può
inserire una propria foto che verrà caricata in un album
prestabilito di una Pagina Facebook di cui si hanno i permessi di gestione. Un
ipotetico scenario può essere una pagina di un concorso basato su foto caricate dagli utenti.
venerdì 16 maggio 2014
Ereditarietà con l'ORM Hibernate
Uno dei problemi dell’Object-Relational Impedance Mismatch (
tratto nell’articolo raggiungibile cliccando sul seguente link: http://lingegnereinformatico.blogspot.it/2014/05/object-relational-impedance-mismatch.html
) è dovuto all’inesistenza del concetto di ereditarietà nel mondo relazionale.
Essendo un elemento fondamentale per il mondo Object-Oriented, è interessante
capire come un ORM come Hibernate permette di risolvere la differenza
concettuale senza impelagarsi in complesse operazioni di conversione.
Object-Relational Impedance Mismatch
Con il termine Object-Relation impedance mismatch ci si
riferisce ad un insieme di problematiche concettuali e tecniche che si
incontrano quando si vuole far dialogare un RDBMS, basato su un modello
relazionale cioè un modello matematico con un programma scritto con un
linguaggio di programmazione orientato agli oggetti ( basato sul paradigma
object-oriented).
Negli ultimi anni, con l’avvento dell’object oriented, esso
è stato oggetto di numerose pubblicazioni. Una trattazione dell’argomento degna
di nota è quella in http://blogs.tedneward.com/2006/06/26/The+Vie%20tnam+Of+Computer+Science.aspx
, dove l’object-relation impedance mismatch viene etichettato come “The Vietnam
of Computer Science”.
Di soluzioni in letteratura ve ne sono parecchie. La più
famosa è l’utilizzo di un ORM.
Tuttavia, lo scopo di questo articolo è concentrarsi sul problema cioè spiegare a livello concettuale quali sono le differenze tra i due modelli:
giovedì 15 maggio 2014
Dalle tabelle agli Oggetti: Reverse Engineering con l'ORM Hibernate
Una casistica da tenere in considerazione quando si utilizza
un ORM per la facilitazione dei meccanismi di persistenza è quella in cui il
prodotto software che si intende realizzare dipende da una base dati esistente.
Nel caso di utilizzo di un ORM affermato come Hibernate è
importante conoscere in che maniera si può passare dalle tabelle già esistenti
agli oggetti del nostro software in maniera facilitata (operazione definita
Reverse Engineering).
Recuperare i risultati di una ricerca Google in PHP
In questo articolo vi mostrerò uno snippet in PHP per recuperare i risultati di una ricerca di una parola chiave effettuata con il motore di ricerca Google.
mercoledì 14 maggio 2014
Pagina per controllo dell'età dell'utente in Javascript ( Agegate )
PROBLEMA: Si vuole permettere l'accesso a dei contenuti di un sito web soltanto dopo che l'utente inserisce la propria data di nascita. L'accesso deve essere consentito solo a chi è maggiorenne.
SOLUZIONE: Per meglio comprendere come si procederà nella soluzione è opportuno evidenziare a grandi linee quello che sarà fatto:
I tre tag INPUT identificano rispettivamente i campi giorno, mese e anno di nascita (indicati in ROSSO).
Il div con l'id content (indicato in VERDE) avrà all'interno i contenuti che si vogliono visualizzare solo ai maggiorenni. (Per semplicità nella spiegazione il contenuto è inserito nello stesso file ma come vedremo negli sviluppi futuri nel punto 2 si potrebbe migliorare lo script con qualche accorgimento )
A questo file html associamo un file css con il seguente contenuto:
#buttonSubmit
{
width:50px;
}
#content
{
display:none;
}
Il file css è indispensabile per poter nascondere il contenuto attraverso il display:none.
A questo punto nel file html creato vi sono dei richiami a delle funzioni javascript che andremo a dettagliare al seguito:
Funzioni richiamate al caricamento della pagina HTML: initPageEta() e leggiCookie()
Quando viene caricata la pagina per la prima volta la funzione richiamata nell'OnLoad del body controlla se il client ha un Cookie di nome maggiorenne settato a 1. In caso affermativo vorrà dire che l'utente ha già visitato il sito ed è già stato riconosciuto come maggiorenne. Per questo, l'operazione da eseguire sarà quella di nascondere la form del controllo dell'età e mostrare i contenuti per maggiorenni.
function initPageEta()
{
var cookieEta=parseInt(leggiCookie('maggiorenne'));
if(cookieEta==1)
{
document.getElementById("controlloEta").style.display="none";
document.getElementById("content").style.display="inline";
}
}
function leggiCookie(nomeCookie)
{
if (document.cookie.length > 0)
{
var inizio = document.cookie.indexOf(nomeCookie + "=");
if (inizio != -1)
{
inizio = inizio + nomeCookie.length + 1;
var fine = document.cookie.indexOf(";",inizio);
if (fine == -1) fine = document.cookie.length;
return unescape(document.cookie.substring(inizio,fine));
}
else
{
return "";
}
}
return "";
}
Funzione richiamata al rilascio di un tasto premuto: input_onchange()
La funzione sposta il focus tra i diversi input per permettere un inserimento lineare della data
Funzioni utilizzate quando si clicca sul pulsante per l'invio della data di nascita: inviaData(), validaData(), maggioreEta()
La funzione ValidaData controlla che la data inserita sia valida.
In caso negativo colora gli input della pagina in rosso.
La funzione maggioreEta() controlla che a partire dalla data di nascita inserita l'utente abbia già compiuto i 18 anni. In caso affermativo vengono visualizzati i contenuti per maggiorenni e viene settato il cookie "maggiorenne" a 1 per agevolare i successivi accessi al sito.
function inviaData()
{
var giorno=parseInt(document.getElementById("giorno").value,10);
var mese=parseInt(document.getElementById("mese").value,10);
var anno=parseInt(document.getElementById("anno").value,10);
if(!validaData(giorno,mese,anno))
{
document.getElementById("giorno").style.border="1px solid red";
document.getElementById("mese").style.border="1px solid red";
document.getElementById("anno").style.border="1px solid red";
}
else
{
if(maggioreEta(giorno,mese,anno))
{
document.getElementById("controlloEta").style.display="none";
document.cookie = 'maggiorenne=1; expires=Tue, 23 June 2015 22:47:11 UTC; path=/';
document.getElementById("content").style.display="inline";
}
else
{
location.href = "URL DELLA PAGINA PER MINORENNI"
}
}
}
function validaData(giorno,mese,anno)
{
var data=new Date(anno, mese-1, giorno);
if(data.getFullYear()==anno && data.getMonth()+1==mese && data.getDate()==giorno){
return true;
}else{
return false;
}
}
function maggioreEta(giorno,mese,anno)
{
var today = new Date();
var birthDate=new Date(anno, mese-1, giorno);
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate()))
{
age--;
}
if(age>= 18)
{
return true;
}
else
return false;
}
SVILUPPI FUTURI:
SOLUZIONE: Per meglio comprendere come si procederà nella soluzione è opportuno evidenziare a grandi linee quello che sarà fatto:
- Bisogna controllare che la data inserita esista (ESEMPIO: 32 Febbraio 2010 non è una data valida)
- Si hanno dei contenuti da visualizzare solo per i maggiorenni.
- Si ha una pagina da visualizzare nel caso in cui l'utente è minorenne.
- Ad un utente maggiorenne che ha già inserito la data di nascita in maniera corretta saranno visualizzati direttamente i contenuti per maggiorenni.
Come primo passo creiamo un file home.html nel quale inseriremo il seguente codice HTML:
<body onLoad="initPageEta()">
<div id="controlloEta">
<input id="giorno" type="text" name="giorno" size="2" maxlength="2" onkeyup="input_onchange('giorno')">
<input id="mese" type="text" name="mese" size="2" maxlength="2" onkeyup="input_onchange('mese')">
<input id="anno" type="text" name="anno" size="4" maxlength="4" onkeyup="input_onchange('anno')">
<button id="buttonSubmit" onClick="inviaData()" > Invia</button>
</div>
<div id="content">
CIAO CLIENTE! CONTENUTI SEGRETI PER I MAGGIORENNI
</div>
</body>
I tre tag INPUT identificano rispettivamente i campi giorno, mese e anno di nascita (indicati in ROSSO).
Il div con l'id content (indicato in VERDE) avrà all'interno i contenuti che si vogliono visualizzare solo ai maggiorenni. (Per semplicità nella spiegazione il contenuto è inserito nello stesso file ma come vedremo negli sviluppi futuri nel punto 2 si potrebbe migliorare lo script con qualche accorgimento )
A questo file html associamo un file css con il seguente contenuto:
#buttonSubmit
{
width:50px;
}
#content
{
display:none;
}
A questo punto nel file html creato vi sono dei richiami a delle funzioni javascript che andremo a dettagliare al seguito:
Funzioni richiamate al caricamento della pagina HTML: initPageEta() e leggiCookie()
Quando viene caricata la pagina per la prima volta la funzione richiamata nell'OnLoad del body controlla se il client ha un Cookie di nome maggiorenne settato a 1. In caso affermativo vorrà dire che l'utente ha già visitato il sito ed è già stato riconosciuto come maggiorenne. Per questo, l'operazione da eseguire sarà quella di nascondere la form del controllo dell'età e mostrare i contenuti per maggiorenni.
function initPageEta()
{
var cookieEta=parseInt(leggiCookie('maggiorenne'));
if(cookieEta==1)
{
document.getElementById("controlloEta").style.display="none";
document.getElementById("content").style.display="inline";
}
}
function leggiCookie(nomeCookie)
{
if (document.cookie.length > 0)
{
var inizio = document.cookie.indexOf(nomeCookie + "=");
if (inizio != -1)
{
inizio = inizio + nomeCookie.length + 1;
var fine = document.cookie.indexOf(";",inizio);
if (fine == -1) fine = document.cookie.length;
return unescape(document.cookie.substring(inizio,fine));
}
else
{
return "";
}
}
return "";
}
Funzione richiamata al rilascio di un tasto premuto: input_onchange()
La funzione sposta il focus tra i diversi input per permettere un inserimento lineare della data
function input_onchange(input)
{
var inputElement= document.getElementById(input);
if(input=='giorno' || input=='mese')
{
if(inputElement.value.length!=2)
return;
}
if(input=='anno')
{
if(inputElement.value.length!=4)
return;
}
if(input=='giorno')
{
document.getElementById('mese').focus();
}
else if(input=='mese')
{
document.getElementById('anno').focus();
}
}
Funzioni utilizzate quando si clicca sul pulsante per l'invio della data di nascita: inviaData(), validaData(), maggioreEta()
La funzione ValidaData controlla che la data inserita sia valida.
In caso negativo colora gli input della pagina in rosso.
La funzione maggioreEta() controlla che a partire dalla data di nascita inserita l'utente abbia già compiuto i 18 anni. In caso affermativo vengono visualizzati i contenuti per maggiorenni e viene settato il cookie "maggiorenne" a 1 per agevolare i successivi accessi al sito.
function inviaData()
{
var giorno=parseInt(document.getElementById("giorno").value,10);
var mese=parseInt(document.getElementById("mese").value,10);
var anno=parseInt(document.getElementById("anno").value,10);
if(!validaData(giorno,mese,anno))
{
document.getElementById("giorno").style.border="1px solid red";
document.getElementById("mese").style.border="1px solid red";
document.getElementById("anno").style.border="1px solid red";
}
else
{
if(maggioreEta(giorno,mese,anno))
{
document.getElementById("controlloEta").style.display="none";
document.cookie = 'maggiorenne=1; expires=Tue, 23 June 2015 22:47:11 UTC; path=/';
document.getElementById("content").style.display="inline";
}
else
{
location.href = "URL DELLA PAGINA PER MINORENNI"
}
}
}
function validaData(giorno,mese,anno)
{
var data=new Date(anno, mese-1, giorno);
if(data.getFullYear()==anno && data.getMonth()+1==mese && data.getDate()==giorno){
return true;
}else{
return false;
}
}
function maggioreEta(giorno,mese,anno)
{
var today = new Date();
var birthDate=new Date(anno, mese-1, giorno);
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate()))
{
age--;
}
if(age>= 18)
{
return true;
}
else
return false;
}
SVILUPPI FUTURI:
- Si potrebbe permettere l'inserimento della data utilizzando un date picker.
- I contenuti riservati ai maggiorenni nella soluzione presentata vengono comunque inviati al client. Si potrebbe aggiungere un controllo lato server e inviare i contenuti solo agli effettivi maggiorenni.
Recuperare gli attributi di una classe a runtime in Java
Field[] fields = Class.forName("NomeClasse").getDeclaredFields();
for(int i=0;i<fields.length;i++)
{
System.out.println("L'attributo numero "+i+" è: "+fields[i].getName());
}
Gestione della memoria in Android: Heap, Garbage Collector e Memory leak
Per poter realizzare applicazioni che gestiscono una mole di dati non indifferente risulta necessario conoscere al meglio come Android gestisce la memoria nei propri dispositivi. Con questo articolo l'intenzione è quella di offrire delle conoscenze basilari al riguardo.
Il primo elemento da conoscere è la memoria Heap che è un'area di memoria in cui le applicazioni in esecuzione possono inserire i propri dati in maniera dinamica. La sua dimensione varia in maniera dinamica ma rimane all'interno di un valore massimo chiamato heap size che dipende dal tipo di device. Per comprendere al meglio, un esempio di Heap per il caro vecchio Nexus one (presentato nel 2010) è di 32 MB nonostante i 512 MB di RAM a disposizione.
Vi sono un paio di motivazioni per le quali Android pone questo limite. Una delle grandi caratteristiche di Android è il multitasking, che permette di avere più applicazioni che girano nello stesso momento. Di conseguenza, non è opportuno permettere ad una singola applicazione di utilizzare l'intera memoria del device. Inoltre, i dispositivi devono avere una certa reattività quando si utilizzano più applicazioni.
A causa di questo limite, se una applicazione dovesse richiedere più memoria di quella messa a disposizione dal dispositivo si otterrebbe un errore di Out Of Memory. Essendo la heap size diversa a seconda del device, Android permette di conoscere dinamicamente quanta memoria si ha a disposizione per la propria applicazione. Vi è un metodo che può essere utilizzato nell' ActivityManager: getMemoryClass() che restituisce un valore intero in Megabytes che rappresenta la nostra Heap Size.
Per applicazioni che richiedono maggiore memoria Heap è possibile settare l'attributo largeHeap a true nel proprio Manifest file. In tal caso si può utilizzare il metodo getLargeMemoryClass() per avere una stima della grandezza della memoria a disposizione.
A fronte di questa premessa, un ruolo fondamentale per la gestione automatica della memoria è ricoperto da un "netturbino" cioè il Garbage Collector.
Per Garbage Collection (letteralmente raccolta dei rifiuti, a volte abbreviato con GC) si intende una modalità automatica di gestione della memoria, mediante la quale Android libera le porzioni di memoria che non dovranno più essere successivamente utilizzate dalle applicazioni. In altre parole, il Garbage Collector annoterà le aree di memoria che non sono più referenziate, cioè allocate da un processo attivo, e le
libererà automaticamente. Il principio di funzionamento del Garbage Collector è piuttosto semplice. Si hanno in memoria un insieme di oggetti (indicati con il colore blu in Figura 1). Ogni oggetto può avere un riferimento ad un altro presente nella heap.
In un particolare istante vi possono essere degli oggetti che non sono più referenziati da nessun altro oggetto. In tal caso essi sono considerati inutilizzati. Il garbage collector eseguirà l'azione di "raccolta rifiuti" su dei particolari
oggetti chiamati root. Questi oggetti sono sicuramente utilizzati dall'applicazione come per esempio dei riferimenti globali. Partendo da essi, il Garbage Collector visita i nodi del grafo attraverso i vari riferimenti. Al termine di tale processo vi saranno dei nodi non visitati che corrispondono ad oggetti inutilizzati e che, in
seguito, saranno eliminati e la memoria sarà recuperata. E' utile sottolineare come questo processo possa essere eseguito per un lasso di tempo variabile a seconda della heap size. Nelle versioni precedenti quella di Gingerbread l'esecuzione del Garbage Collection comportava una interruzione temporanea dell'esecuzione delle applicazioni. Anche se questa pausa risultava essere piuttosto breve, nell'ordine dei 50-100 millisecondi, col crescere della heap avrebbe potuto portare a delle pause non accettabili per applicazioni con particolari esigenze di reattività. Per tale motivo, nella versione di Gingerbread è stato modi cato il processo di Garbage collection in maniera concorrente rispetto all'esecuzione delle applicazioni ed è stato ridotto il tempo di pausa a 4-5 millisecondi.
A questo punto un problema da non sottovalutare è quello del Memory leak.
Un memory leak è un particolare tipo di consumo non voluto di memoria dovuto alla mancata deallocazione dalla memoria di variabili/dati non più utilizzati da parte dei processi. E' bene precisare che la memoria non viene persa fisicamente, piuttosto diventa inutilizzabile per un difetto del software.
In altre parole, si ha un riferimento ad un oggetto in memoria che la nostra applicazione non utilizzerà più e il Garbage Collector non sarà in grado di ripulire la zona di memoria occupata.
Come si fa a monitorare la memoria e a riconoscere eventuali Memory Leak ?
Esiste un tool chiamato Eclipse Memory Analizyer che mi prometto di recensire nelle mie prossime guide.
Per il momento è meglio affrontare per gradi la questione della gestione della memoria.
Ogni qual volta il Garbage Collector entra in azione viene inviato un messaggio di Log visualizzabile tramite il Logcat. Saper leggere questo messaggio risulta essere fondamentale. Un esempio è mostrato in Figura 2.
La prima dicitura (che in Figura 2 è GC CONCURRENT) è la ragione per la quale è stato eseguito il Garbage Collection. Si possono avere diversi casi:
Il primo elemento da conoscere è la memoria Heap che è un'area di memoria in cui le applicazioni in esecuzione possono inserire i propri dati in maniera dinamica. La sua dimensione varia in maniera dinamica ma rimane all'interno di un valore massimo chiamato heap size che dipende dal tipo di device. Per comprendere al meglio, un esempio di Heap per il caro vecchio Nexus one (presentato nel 2010) è di 32 MB nonostante i 512 MB di RAM a disposizione.
Vi sono un paio di motivazioni per le quali Android pone questo limite. Una delle grandi caratteristiche di Android è il multitasking, che permette di avere più applicazioni che girano nello stesso momento. Di conseguenza, non è opportuno permettere ad una singola applicazione di utilizzare l'intera memoria del device. Inoltre, i dispositivi devono avere una certa reattività quando si utilizzano più applicazioni.
A causa di questo limite, se una applicazione dovesse richiedere più memoria di quella messa a disposizione dal dispositivo si otterrebbe un errore di Out Of Memory. Essendo la heap size diversa a seconda del device, Android permette di conoscere dinamicamente quanta memoria si ha a disposizione per la propria applicazione. Vi è un metodo che può essere utilizzato nell' ActivityManager: getMemoryClass() che restituisce un valore intero in Megabytes che rappresenta la nostra Heap Size.
Per applicazioni che richiedono maggiore memoria Heap è possibile settare l'attributo largeHeap a true nel proprio Manifest file. In tal caso si può utilizzare il metodo getLargeMemoryClass() per avere una stima della grandezza della memoria a disposizione.
A fronte di questa premessa, un ruolo fondamentale per la gestione automatica della memoria è ricoperto da un "netturbino" cioè il Garbage Collector.
Per Garbage Collection (letteralmente raccolta dei rifiuti, a volte abbreviato con GC) si intende una modalità automatica di gestione della memoria, mediante la quale Android libera le porzioni di memoria che non dovranno più essere successivamente utilizzate dalle applicazioni. In altre parole, il Garbage Collector annoterà le aree di memoria che non sono più referenziate, cioè allocate da un processo attivo, e le
libererà automaticamente. Il principio di funzionamento del Garbage Collector è piuttosto semplice. Si hanno in memoria un insieme di oggetti (indicati con il colore blu in Figura 1). Ogni oggetto può avere un riferimento ad un altro presente nella heap.
![]() |
Figura 1 - Gli oggetti in memoria |
oggetti chiamati root. Questi oggetti sono sicuramente utilizzati dall'applicazione come per esempio dei riferimenti globali. Partendo da essi, il Garbage Collector visita i nodi del grafo attraverso i vari riferimenti. Al termine di tale processo vi saranno dei nodi non visitati che corrispondono ad oggetti inutilizzati e che, in
seguito, saranno eliminati e la memoria sarà recuperata. E' utile sottolineare come questo processo possa essere eseguito per un lasso di tempo variabile a seconda della heap size. Nelle versioni precedenti quella di Gingerbread l'esecuzione del Garbage Collection comportava una interruzione temporanea dell'esecuzione delle applicazioni. Anche se questa pausa risultava essere piuttosto breve, nell'ordine dei 50-100 millisecondi, col crescere della heap avrebbe potuto portare a delle pause non accettabili per applicazioni con particolari esigenze di reattività. Per tale motivo, nella versione di Gingerbread è stato modi cato il processo di Garbage collection in maniera concorrente rispetto all'esecuzione delle applicazioni ed è stato ridotto il tempo di pausa a 4-5 millisecondi.
A questo punto un problema da non sottovalutare è quello del Memory leak.
Un memory leak è un particolare tipo di consumo non voluto di memoria dovuto alla mancata deallocazione dalla memoria di variabili/dati non più utilizzati da parte dei processi. E' bene precisare che la memoria non viene persa fisicamente, piuttosto diventa inutilizzabile per un difetto del software.
In altre parole, si ha un riferimento ad un oggetto in memoria che la nostra applicazione non utilizzerà più e il Garbage Collector non sarà in grado di ripulire la zona di memoria occupata.
Come si fa a monitorare la memoria e a riconoscere eventuali Memory Leak ?
Esiste un tool chiamato Eclipse Memory Analizyer che mi prometto di recensire nelle mie prossime guide.
Per il momento è meglio affrontare per gradi la questione della gestione della memoria.
Ogni qual volta il Garbage Collector entra in azione viene inviato un messaggio di Log visualizzabile tramite il Logcat. Saper leggere questo messaggio risulta essere fondamentale. Un esempio è mostrato in Figura 2.
![]() |
Figura 2 - Messaggio di Log del Garbage Collector |
- GC CONCURRENT: Viene eseguita in maniera concorrente quando l'heap comincia a riempirsi.
- GC FOR MALLOC: Non è stato completato GC CONCURRENT in tempo e l'applicazione ha allocato più memoria. L'heap risulta piena e quindi il sistema blocca l'esecuzione dell'applicazione per far spazio al garbage collector.
- GC EXTERNAL ALLOC: Quando viene eseguito il garbage collector nella memoria nativa.
- GC HPROF DUMP HEAP: quando viene creato un HPROF file per l'analisi della memoria tramite il tool Eclipse Memory Analyzer
- GC EXPLICIT: Quando viene richiamato in maniera esplicita l'istruzione System.gc (DA EVITARE)
Nella parte successiva vengono indicate le seguenti informazioni in ordine di visualizzazione:
- Quanta memoria in kb viene liberata in seguito al passaggio del Garbage Collector.
- La percentuale di memoria libera dopo il passaggio del garbage collector.
- Quanta memoria è occupata dagli oggetti presenti nella heap e quant' è la dimensione della heap.
- La dicitura external si riferisce alla memoria nativa. La coppia di dati indica quanta memoria è attualmente occupata e a quanto ammonta il limite imposto dal sistema oltre il quale viene richiamato il processo di Garbage Collector.
- Con la dicitura pause time si indica il tempo di pausa per l'esecuzione del Garbage Collector.
martedì 13 maggio 2014
Creare pagine con categorie per articoli in Blogger
Sul web molto spesso si trovano soluzioni semplici e veloci ma non è il caso del problema trattato in questo articolo: creare delle pagine e collegarle alle categorie degli articoli in Blogger. In CMS come Joomla o Wordpress le cose sono molto più intuitive, ma secondo me non più semplici. Ecco la mia soluzione con Blogger:
Quando si crea un articolo è opportuno indicare le etichette, cioè le parole chiavi che potrebbero facilitare il reperimento dell'articolo. Ebbene, si pensi alle etichette come alle categorie.
Se si sta scrivendo un articolo per una categoria Calcio è sufficiente aggiungere l'etichetta "calcio" (il numero di etichette può essere maggiore di uno).
A questo punto è sufficiente:
1) Entrare nel pannello di amministrazione del nostro Blog.
2) Selezionare il pulsante relativo al Layout e aggiungere il gadget di nome Pagine.
3) Entrare nella pagina di configurazione del widget.
4) Cliccare su Aggiungi link esterno
5) Aggiungere il seguente link sostituendo il nome del vostro blog e la categoria di interesse: http:// NOME DEL BLOG .blogspot.it/search/label/CATEGORIA
Con questi semplici passi avremo le pagine collegate con le categorie (o meglio etichette).
Per alcuni modelli potrebbe essere visualizzato il fastidioso messaggio di questo tipo:
Visualizzazione degli ultimi post con etichetta (nome etichetta).
Per fare in modo che non appaia vi consiglio di agire nelle impostazioni del vostro Blog -> Modello -> Modifica HTML
e commentare l'html che non gradite. Nel caso del modello che ho scelto nel mio blog le righe (all'incirca 2040) commentate sono le seguenti:
<!-- <b:if cond='data:navMessage'>
<div class='status-msg-wrap'>
<div class='status-msg-body'>
<data:navMessage/>
</div>
<div class='status-msg-border'>
<div class='status-msg-bg'>
<div class='status-msg-hidden'><data:navMessage/></div>
</div>
</div>
</div>
<div style='clear: both;'/>
</b:if> -->
Quando si crea un articolo è opportuno indicare le etichette, cioè le parole chiavi che potrebbero facilitare il reperimento dell'articolo. Ebbene, si pensi alle etichette come alle categorie.
Se si sta scrivendo un articolo per una categoria Calcio è sufficiente aggiungere l'etichetta "calcio" (il numero di etichette può essere maggiore di uno).
A questo punto è sufficiente:
1) Entrare nel pannello di amministrazione del nostro Blog.
2) Selezionare il pulsante relativo al Layout e aggiungere il gadget di nome Pagine.
3) Entrare nella pagina di configurazione del widget.
4) Cliccare su Aggiungi link esterno
5) Aggiungere il seguente link sostituendo il nome del vostro blog e la categoria di interesse: http:// NOME DEL BLOG .blogspot.it/search/label/CATEGORIA
Con questi semplici passi avremo le pagine collegate con le categorie (o meglio etichette).
Per alcuni modelli potrebbe essere visualizzato il fastidioso messaggio di questo tipo:
Visualizzazione degli ultimi post con etichetta (nome etichetta).
Per fare in modo che non appaia vi consiglio di agire nelle impostazioni del vostro Blog -> Modello -> Modifica HTML
e commentare l'html che non gradite. Nel caso del modello che ho scelto nel mio blog le righe (all'incirca 2040) commentate sono le seguenti:
<!-- <b:if cond='data:navMessage'>
<div class='status-msg-wrap'>
<div class='status-msg-body'>
<data:navMessage/>
</div>
<div class='status-msg-border'>
<div class='status-msg-bg'>
<div class='status-msg-hidden'><data:navMessage/></div>
</div>
</div>
</div>
<div style='clear: both;'/>
</b:if> -->
domenica 11 maggio 2014
Un ORM per Android: ORMLite
Concentrare gli sforzi di sviluppo sulle logiche di business e sulle esigenze degli utenti piuttosto che sulle sugli elementi tecnologici è un aspetto cruciale per il successo del software. L'utilizzo di un ORM per sviluppare un'applicazione di qualsiasi tipo oggi risulta essere indispensabile per la gestione della persistenza degli oggetti attraverso una base dati. Ho deciso di realizzare questa piccola guida per poter agevolare l'utilizzo di un ORM in un ambiente mobile come per esempio Android. L'ORM scelto è ORMLite.
Introduzione
ORMLite fornisce delle funzionalità leggere per il problema dell'ORM (Object Relational Mapping) tra classi Java e un database SQL. Seppure esistono soluzioni ORM molto più mature (come per esempio Hibernate), questa libreria risulta utile soprattutto per la la semplicità di utilizzo e la complessità ridotta. Quest'ultima caratteristica la rende adatta per contesti dove le risorse sono limitate (smartphone). Insieme a questo vantaggio, nella documentazione reperibile nel sito ufficiale si offre ampio supporto al mondo Android.
Prima di procedere è bene precisare che a causa della mancanza del supporto per i JDBC in Android, ORMLite utilizza in maniera diretta le API native per l'accesso ai database SQL.
Download e import
La prima operazione da compiere è quella di scaricare l'ultima release dal seguente link http://ormlite.com/releases/. La versione di riferimento per questa guida è la 4.48 e risale a Dicembre 2013.
Come si può notare una volta cliccato il link, vi sono tre file jar da poter scaricare identificati con i seguenti nomi: Core, JDBC e Android.
Per l'utilizzo dell'ORM in una applicazione Android è sufficiente scaricare i soli file jar relativi al core e Android.
Dopo aver creato il progetto bisogna aprire il pannello della configurazione del Build Path (scheda Libraries) e aggiungere come External JARs i due file scaricati.
Creare le classi persistenti
Per utilizzare il concetto di persistenza attraverso ORMLite si utilizzano le annotazioni di Java.
Per fare questo ho preparato un esempio banale di una ipotetica classe Studente:
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "studente")
public class Studente {
@DatabaseField(id = true)
private String numeroMatricola;
@DatabaseField
private String nome;
@DatabaseField
private String cognome;
public Studente()
{
}
public String getNumeroMatricola() {
return numeroMatricola;
}
public void setNumeroMatricola(String numeroMatricola) {
this.numeroMatricola = numeroMatricola;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCognome() {
return cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
}
I due requisiti fondamentali per classi di questo tipo sono:
Introduzione
ORMLite fornisce delle funzionalità leggere per il problema dell'ORM (Object Relational Mapping) tra classi Java e un database SQL. Seppure esistono soluzioni ORM molto più mature (come per esempio Hibernate), questa libreria risulta utile soprattutto per la la semplicità di utilizzo e la complessità ridotta. Quest'ultima caratteristica la rende adatta per contesti dove le risorse sono limitate (smartphone). Insieme a questo vantaggio, nella documentazione reperibile nel sito ufficiale si offre ampio supporto al mondo Android.
Prima di procedere è bene precisare che a causa della mancanza del supporto per i JDBC in Android, ORMLite utilizza in maniera diretta le API native per l'accesso ai database SQL.
Download e import
La prima operazione da compiere è quella di scaricare l'ultima release dal seguente link http://ormlite.com/releases/. La versione di riferimento per questa guida è la 4.48 e risale a Dicembre 2013.
Come si può notare una volta cliccato il link, vi sono tre file jar da poter scaricare identificati con i seguenti nomi: Core, JDBC e Android.
Per l'utilizzo dell'ORM in una applicazione Android è sufficiente scaricare i soli file jar relativi al core e Android.
Dopo aver creato il progetto bisogna aprire il pannello della configurazione del Build Path (scheda Libraries) e aggiungere come External JARs i due file scaricati.
Creare le classi persistenti
Per utilizzare il concetto di persistenza attraverso ORMLite si utilizzano le annotazioni di Java.
Per fare questo ho preparato un esempio banale di una ipotetica classe Studente:
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "studente")
public class Studente {
@DatabaseField(id = true)
private String numeroMatricola;
@DatabaseField
private String nome;
@DatabaseField
private String cognome;
public Studente()
{
}
public String getNumeroMatricola() {
return numeroMatricola;
}
public void setNumeroMatricola(String numeroMatricola) {
this.numeroMatricola = numeroMatricola;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCognome() {
return cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
}
- L'import delle librerie.
- Costruttore vuoto.
Progettare uno strato per la persistenza
A questo punto la domanda alla quale bisognerà trovare risposta è:
Esiste un modo per progettare uno strato con la responsabilità di gestire la persistenza in maniera tale da ottimizzare il riuso del codice? O meglio, posso realizzare un componente indipendente che posso utilizzare in tutti i miei progetti Android per la gestione della persistenza?
L'idea di massima è quella di creare un package di nome persistence accessibile attraverso una sola classe identificata con il suffisso Facade (dal pattern omonimo). Tutti i messaggi scambiati con lo strato passeranno attraverso questa classe. Questo è un aspetto cruciale per il riuso in quanto tutto quello che è nel sottosistema deve essere inesistente per le classi utilizzatrici di esso. Un esempio di una ipotetica classe Facade con le funzionalità di salvataggio, cancellazione e recupero di oggetti è mostrato nella figura che segue:
Per qualsiasi oggetto che venga passato ai metodi indicati, lo strato persistence deve essere in grado di eseguire la funzionalità prevista.
Ma come faccio ad implementare tutto questo?
Ho realizzato una piccola implementazione che per stimolare il lettore NON condividerò qui sul mio blog (se volete le classi con il codice potete scrivere come commento la vostra mail e ve le manderò senza problemi).
Piuttosto vi condivido i passi chiave:
1) Recuperate l'esempio intitolato HelloAndroid di ORMLite e scaricate i file HelloAndroid e DatabaseHelper (il link è il seguente http://ormlite.com/android/examples/)
2) Aggiungeteli al vostro progetto con l'accortezza di creare un package persistence e porvi all'interno la classe DatabaseHelper.
3) Create una classe PersistenceFacade nel package persistence che rispetti il pattern Singleton in questo modo (notate la parola chiave static per il metodo e l'attributo):
public static PersistenceFacade instance = null;
public static PersistenceFacade getInstance()
{
if (instance==null)
instance=new PersistenceFacade();
return instance;
}
private PersistenceFacade()
{
}
4) Bisogna modificare alcuni metodi del DatabaseHelper. Qui viene il bello e preferisco che il lettore "provi" a realizzarlo. (Nel caso in cui non ci riusciate non esitate a chiedere ulteriori chiarimenti)
L'idea di base è quella di porre i nomi delle classi persistenti in una risorsa esterna, sfruttando i file XML tipici di Android. Sarà sufficiente utilizzare la reflection per fare in modo che lo strato persistence non dipenda dal nostro strato di dominio. Leggendo dalla risorsa esterna le classi da rendere persistenti il metodo onCreate della classe DatabaseHelper creerà tutte le tabelle necessarie.
Ciò è un vantaggio in relazione a modifiche future o riuso del codice: aggiungere una riga di XML è sufficiente per poter creare la tabella sul proprio db.
5) A questo punto non rimane altro che scrivere gli infiniti metodi che si vogliono utilizzare per la persistenza in maniera del tutto generale (sfruttando il polimorfismo). Un esempio di metodo save sarà:
public void Save(Object obj)
{
RuntimeExceptionDao<Object, Integer> simpleDao = (RuntimeExceptionDao<Object, Integer>) this.getDbHelper().getSimpleDataDao(obj.getClass().getName());
simpleDao.create(obj);
}
Il lettore può notare che le righe di codice sono ridotte a due e l'utilizzo dell'Object consente il riuso del metodo per qualsiasi tipo di oggetto si voglia rendere persistente purchè sia stato dichiarato nel file XML menzionato nel punto 4.
A questo punto il lavoro è completo. Sarà sufficiente ampliare il numero di metodi pensati per la persistenza come per esempio Delete, GetAll, etc...
Ai lettori più curiosi che sono arrivati fino a questo punto dell'articolo chiedo:
Pro e Contro di questo approccio?
- Costruttore vuoto.
Progettare uno strato per la persistenza
A questo punto la domanda alla quale bisognerà trovare risposta è:
Esiste un modo per progettare uno strato con la responsabilità di gestire la persistenza in maniera tale da ottimizzare il riuso del codice? O meglio, posso realizzare un componente indipendente che posso utilizzare in tutti i miei progetti Android per la gestione della persistenza?
L'idea di massima è quella di creare un package di nome persistence accessibile attraverso una sola classe identificata con il suffisso Facade (dal pattern omonimo). Tutti i messaggi scambiati con lo strato passeranno attraverso questa classe. Questo è un aspetto cruciale per il riuso in quanto tutto quello che è nel sottosistema deve essere inesistente per le classi utilizzatrici di esso. Un esempio di una ipotetica classe Facade con le funzionalità di salvataggio, cancellazione e recupero di oggetti è mostrato nella figura che segue:
Per qualsiasi oggetto che venga passato ai metodi indicati, lo strato persistence deve essere in grado di eseguire la funzionalità prevista.
Ma come faccio ad implementare tutto questo?
Ho realizzato una piccola implementazione che per stimolare il lettore NON condividerò qui sul mio blog (se volete le classi con il codice potete scrivere come commento la vostra mail e ve le manderò senza problemi).
Piuttosto vi condivido i passi chiave:
1) Recuperate l'esempio intitolato HelloAndroid di ORMLite e scaricate i file HelloAndroid e DatabaseHelper (il link è il seguente http://ormlite.com/android/examples/)
2) Aggiungeteli al vostro progetto con l'accortezza di creare un package persistence e porvi all'interno la classe DatabaseHelper.
3) Create una classe PersistenceFacade nel package persistence che rispetti il pattern Singleton in questo modo (notate la parola chiave static per il metodo e l'attributo):
public static PersistenceFacade instance = null;
public static PersistenceFacade getInstance()
{
if (instance==null)
instance=new PersistenceFacade();
return instance;
}
private PersistenceFacade()
{
}
4) Bisogna modificare alcuni metodi del DatabaseHelper. Qui viene il bello e preferisco che il lettore "provi" a realizzarlo. (Nel caso in cui non ci riusciate non esitate a chiedere ulteriori chiarimenti)
L'idea di base è quella di porre i nomi delle classi persistenti in una risorsa esterna, sfruttando i file XML tipici di Android. Sarà sufficiente utilizzare la reflection per fare in modo che lo strato persistence non dipenda dal nostro strato di dominio. Leggendo dalla risorsa esterna le classi da rendere persistenti il metodo onCreate della classe DatabaseHelper creerà tutte le tabelle necessarie.
Ciò è un vantaggio in relazione a modifiche future o riuso del codice: aggiungere una riga di XML è sufficiente per poter creare la tabella sul proprio db.
5) A questo punto non rimane altro che scrivere gli infiniti metodi che si vogliono utilizzare per la persistenza in maniera del tutto generale (sfruttando il polimorfismo). Un esempio di metodo save sarà:
public void Save(Object obj)
{
RuntimeExceptionDao<Object, Integer> simpleDao = (RuntimeExceptionDao<Object, Integer>) this.getDbHelper().getSimpleDataDao(obj.getClass().getName());
simpleDao.create(obj);
}
Il lettore può notare che le righe di codice sono ridotte a due e l'utilizzo dell'Object consente il riuso del metodo per qualsiasi tipo di oggetto si voglia rendere persistente purchè sia stato dichiarato nel file XML menzionato nel punto 4.
A questo punto il lavoro è completo. Sarà sufficiente ampliare il numero di metodi pensati per la persistenza come per esempio Delete, GetAll, etc...
Ai lettori più curiosi che sono arrivati fino a questo punto dell'articolo chiedo:
Pro e Contro di questo approccio?
Cerca nel blog
Popular Posts
-
Le Inner Class consentono di definire una classe dentro un’altra classe. Ciò ha delle particolarità in termini di visibilità. Di questo as...
-
Un componente di fondamentale importanza nell’architettura Android è il Service. Esso è distinto dall’Activity, in quanto non necessita di ...
-
In questo periodo mi sto cimentando con la certificazione della Oracle Java SE 6 Programmer (ex SCJP). In generale, mi sono accorto che la ...
-
Problema : Quando si installa un server MySQL sul proprio pc, per chiari motivi di sicurezza, qualsiasi connessione sulla porta 3306 viene...
-
PROBLEMA : Si vuole permettere l'accesso a dei contenuti di un sito web soltanto dopo che l'utente inserisce la propria data di nasc...
-
Il Navigation Drawer, in molte occasioni definito come Sliding Menu, è utile per visualizzare le sezioni principali di navigazione della no...
Blog Archive
-
▼
2014
(23)
-
▼
maggio
(17)
- Ridimensionamento immagini in PHP
- Utilizzare i Service in Android
- L'UML in pillole: Diagramma degli oggetti
- Rendere un server MySQL accessibile da remoto
- Estrarre il testo semplice dal codice HTML in Java
- Una galleria di foto collegata con una pagina di F...
- Recuperare il codice seriale di Windows
- Upload di foto su un album di una pagina Facebook ...
- Ereditarietà con l'ORM Hibernate
- Object-Relational Impedance Mismatch
- Dalle tabelle agli Oggetti: Reverse Engineering co...
- Recuperare i risultati di una ricerca Google in PHP
- Pagina per controllo dell'età dell'utente in Javas...
- Recuperare gli attributi di una classe a runtime i...
- Gestione della memoria in Android: Heap, Garbage C...
- Creare pagine con categorie per articoli in Blogger
- Un ORM per Android: ORMLite
-
▼
maggio
(17)
Modulo di contatto
Powered by Blogger.
Copyright ©
L'Ingegnere Informatico | Powered by Blogger
Design by Flythemes | Blogger Theme by NewBloggerThemes.com