Diario di un’applicazione Android – Un po’ di ottimizzazione

Di - 11 March 2013 - in
Post image for Diario di un’applicazione Android – Un po’ di ottimizzazione

Riprendiamo il nostro “cammino” di sviluppo, parlando oggi un po’ di ottimizzazione.

Ogni tanto è sempre bene fare una Review del codice; le prime revisioni sono solitamente scritte per funzionare e, per quanto impegno possiamo metterci, lo scopo è prima quello di vedere qualche cosa che funziona, lasciando ad un secondo momento la fase di ottimizzazione (chiamata anche la causa di tutti i mali.. ma questa è un’altra storia).

Soprattutto se applichiamo un modello “Agile”, in cui lo sviluppo è continuo e vogliamo rilasciare il più presto possibile le funzioni implementate, per ricevere feedback dagli utenti, tenderemo a scrivere del codice che funziona come deve, ma magari non utilizza le best practice o semplicemente “incastriamo” pezzi qua e là (tipo le stringhe dei messaggi).

As Responsive as possible

Come detto nell’articolo relativo alla UI/UX , è bene che l’applicazione risponda sempre in maniera molto rapida; l’utente medio, anche se magari abituato ad applicazioni lentissime per lavoro, vuole e pretende (giustamente IMO), che l’applicazione gli dia un feedback immediato anche fosse solo un “Stiamo lavorando per Voi”.

Nella mia esperienza, chi è abituato alla programmazione funzionale/sequenziale, non è quasi mai abituato a pensare in questi termini; normalmente se viene chiamata una funzione si attende il risultato, magari si tenta di ottimizzare il più possibile l’algoritmo che genera il risultato, ma comunque si attende. Non pensiamo (Yes.. vengo da quella scuola di pensiero) alla possibilità di applicare un metodo più asincrono.

E si che tutti i giorni ci troviamo davanti a queste situazioni, ed inconsciamente applichiamo una metodologia di lavoro a eventi.

Facciamo un esempio: mi serve un documento da archivio, lo chiedo alla segretaria, ma nel mentre non sto ad aspettare che lei lo cerchi negli scaffali; faccio una telefonata, controllo la casella email, mi basta che io capisca che lei ha recepito la mia richiesta e mi notificherà quando il task sarà completato.

Se spezziamo questo processo abbiamo il seguente schema:

  • Faccio una richiesta
  • Ottengo conferma che la richiesta verrà elaborata
  • ottengo nuovamente e celermente il controllo del mio flusso di lavoro
  • ….. lavoro…..
  • Vengo notificato che la mia richiesta è stata completata
  • Utilizzo i dati della mia richiesta

Verissimo che in molti casi, comunque, aspettiamo il risultato della richiesta ma non siamo costretti all’inattività. Qualsiasi cosa accada nel mentre (altri tipi di interazione di varia natura), possiamo rispondere.

Questa logica porta benefici non solo nel mondo mobile o su macchine con poca potenza (giusto perchè c’è ancora qualche device a bassa potenza anche se poi ci tirano fuori smartphone 8core), ma rende tutto più fruibile e scorrevole ( Smooth suona meglio e rende meglio l’idea) anche su applicazioni web e Client.

Immaginatevi un social network dove per ogni click che fate dovete aspettare il post-back dal server, per vedere gli aggiornamenti dovete cliccare sul bottone di refresh…Impensabile al giorno d’oggi.

Per chi conosce la programmazione a Thread o con Eventi Asincorni, sa che normalmente sono fonte di grossi grattacapi, soprattutto in linguaggi storicamente non nati con questi concetti in mente.
Nella mia esperienza di programmatore .Net ci ho sbattuto la testa molte volte e per molto tempo. Ora (.Net 3.5 +) sono presenti dei costrutti abbastanza comodi e robusti, ma in passato, il tempo impiegato a capire come mai veniva generato un errore, e soprattutto da quale thread/task asincrono era stato scatenato, era buona parte dello sviluppo vero e proprio della gestione Asincrona.

Elaborazioni Asincrone su Android

Ora che vi ho spaventati con l’introduzione, vi dico che in Java in generis e più in specifico Android con gli Async Task, la situazione non è poi così drammatica; potrebbero essere le mie esperienze drammatiche a parlare, ma in confronto alla gestione dei thread in .Net 1.1 o linguaggi di più basso livello, bisogna baciarsi i gomiti per gli AsyncTask.

Nella versione 1.1 di NoteToGDocs abbiamo usato degli oggetti Thread per fare in maniera Asincrona le elaborazioni; più che altro perchè obbligati dalle chiamate Drive che possono scatenare delle eccezioni di rete e Android dà un’eccezione se questo codice è eseguito dal thread della UI.

Non vi tedio sull’argomento, ma se volete approfondire c’è una sezione apposita delle API Guides.

Gli AsyncTask sono un’oggetto dell’OS Android che possiamo estendere creando nostre classi che eseguono operazioni in maniera asincrona e possono restituire il risultato alla UI in maniera semplice. Come anche riportato dalla documentazione, è bene però non usarli per operazioni che durano molto tempo (più di qualche secondo) poiché non hanno tutte le funzionalità di un framework per la gestione Async delle operazioni.

Mio parere è che per il 70% dei casi vanno benissimo, se dovete calcolare il 1754esimo numero della serie di Fibonacci magari no, ma per salvare file, aprirli, caricarne 1, è la via più redditizia.

Da Thread ad AsyncTask
La transizione da Thread a Task è abbastanza semplice; come da documentazione gli AsyncTask devono implementare le seguenti funzioni:

  • doInBackgroud: nel nostro codice principale
  • onProgressUpdate: se vogliamo notificare l’applicazione di essere arrivati al 50% dell’elaborazione possiamo farlo con questa funzione che deve essere richiamata da doInBackgroud
  • onPostExecute: da chiamare ad elaborazione terminata

Questo era il codice di upload della nota con il Thread:

Thread t = new Thread(new Runnable() {
	@Override
	public void run() {
	//DO A Barrel Roll and Some Stuff

	//Creo la notifica e una serie di altre operazioni prettamente di UI
	}
});
t.start(); //Avvio il thread che fa tutt

Ora dovremmo spostare il codice di run() in doInBackground ma possiamo fare di meglio e mettere nel posto giusto le varie parti che componevano il codice di run().

Di seguito come dobbiamo costruire l’AsyncTaskClass:

private class UploadNoteTask extends AsyncTask {
	@Override
	protected Boolean doInBackground(String... content) {
		//DO A Barrel Roll and Some Stuff
		return isSaved;
	}
	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);
		//Creo la notifica e una serie di altre operazioni prettamente di UI
	}
}

L’implementazione reale nel codice non l’ho proprio fatta come qui descritto perchè la pigrizia mi ha preso d’assalto e ho solo spostato parte del codice come descritto in questo articolo; ma ora che mi sono accorto sistemo e con la prossima release dell’applicazione il codice sarà corretto e pulito.

Ok… ma è cambiato poco e niente…
A prima vista si, abbiamo solo spostato del codice, ma abbiamo ottenuto i seguenti risultati:

  • Non abbiamo più codice volante nelle funzioni del thread della UI che non faccia operazioni sulla UI
  • Abbiamo una classe strutturata in cui possiamo spezzare il codice, usare variabili con visibilità locale, etc…
  • Android fa il lavoro pesante della gestione degli errori e dell’esecuzione del thread in parallelo

Per il momento fidatevi, ma se date uno sguardo al sorgente di NoteToGDocs nella classe Activity trovate la private class NotesListTask che essendo stata creata direttamente come AsyncTask ne sfrutta maggiormente le potenzialità.

Per il momento il diario di un’applicazione Android va in vacanza per poter lasciarmi più tempo da dedicare allo sviluppo di applicazioni Android (un NDA mi impedisce di dire di più ;-).
Se avete dubbi/commenti potete sempre contattarmi attraverso la mia pagina di Google Plus, per il momento ringrazio tutti quelli che hanno seguito questo breve diario e spero abbiate gradito.

Leave a Reply

Articolo scritto da

Techy, sviluppatore .Net per professione, sviluppatore Android per passione. All Around Android Lover e Google Enthusiast

Contatta l'autore

Previous post:

Next post: