DevCorner: Lezione 1 - Creiamo una prima richiesta asincrona [METEO]

Roberto Orgiu
Roberto Orgiu
DevCorner: Lezione 1 - Creiamo una prima richiesta asincrona [METEO]

Abbiamo visto nelle scorse puntate della nostra rubrica qual'è la piega che prenderà il DevCorner, almeno per qualche mese: diamoci quindi subito all'azione e vediamo cosa ci riserva oggi la rubrica sulla programmazione di AndroidWorld.it.

Dirigiamoci quindi su GitHub dove, volta per volta, aggiorneremo i sorgenti della nostra app, in modo da vederla crescere tutti insieme: da questa pagina, potete forkare il progetto, scaricarlo come archivio oppure, se preferite, createne uno vuoto sulle vostre macchine, utilizzando l'IDE che preferite: in redazione, sviluppiamo su Android Studio, ma sentitevi liberi di utilizzare IntelliJ IDEA oppure Eclipse, a seconda delle vostre abitudini.

Iniziamo quindi il primo step della nostra applicazione con un passo fondamentale: ottenere le previsioni meteorologiche data una precisa locazione. Per questa applicazione, ci siamo affidati al utile servizio offerto da Metwit, preferendolo all'ottima libreria WeatherLib per ragioni puramente programmatiche: volevamo, in questa prima fase, affrontare le problematiche di rete ad un livello quanto più concreto possibile, ragion per cui ci siamo affidati ad un servizio REST come quello offerto dal già citato portale.

La richiesta da fare al servizio deve puntare a questo indirizzo e ci basterà una semplice HttpGet per ottenere la risposta che ci serve:

final String requestUri = String.format(URL_FORMAT, strings[0], strings[1]);
final HttpClient httpClient = new DefaultHttpClient();
final HttpGet httpRequest = new HttpGet(requestUri);
final HttpResponse httpResponse = httpClient.execute(httpRequest);
String response = EntityUtils.toString(httpResponse.getEntity());

Proviamo ad analizzare il codice: nella prima riga, accodiamo i parametri di latitudine e longitudine contenuti nel vettore strings all'indirizzo che dobbiamo contattare, in modo da poter modificare la località senza sforzo (ci basterà infatti passare coordinate differenti per poter ottenere un'altra richiesta valida). Nella seconda riga, abbiamo creato un nuovo client Http, che si preoccuperà di effettuare la richiesta di tipo GET (che dichiariamo nella riga successiva, passando in ingresso la stringa contenente l'URL) e ci tornerà la risposta nella quarta riga. Infine, analizzeremo la risposta grazie alle risorse contenute in EntityUtils.

Come possiamo vedere, effettuare la richiesta in sé non è nulla di complicato ma può riservare alcune insidie: per prima cosa, dobbiamo assolutamente prevedere di effettuare tute le operazioni lunghe, come le richieste di rete, su un thread a parte. Per quale motivo? In primis, altrimenti Android ucciderà la nostra applicazione con una NetworkOnMainThreadException (NdA: questo limite si può aggirare, ma non è assolutamente buona norma disattivare lo strict mode per aggirare il divieto) e, fattore non meno importante, l'attesa per il completamento delle operazioni più lunghe blocca il thread dell'interfaccia, causando quindi un'esperienza utente povera. Per chiarirci le idee, immaginiamo di essere connessi in 2G e provare ad effettuare una richiesta: se agissimo sul thread principale, la nostra applicazione si congelerebbe fino al termine della richiesta che, come sappiamo bene, durerebbe troppo, al punto da farci perdere la pazienza ed indurci a chiudere l'app. Per evitare questi spiacevoli disguidi, sposteremo quindi la richiesta su un thread in background, utilizzando per questa prima lezione un AsyncTask, come possiamo vedere dai sorgenti.

Vedremo però che, benché questa classe si riveli utile in diverse circostanze, non è la più indicata per tutte le operazioni: se, ad esempio, ruotassimo il dispositivo mentre l'AsyncTask sta ancora eseguendo la doInBackground, il task verrebbe annullato e la onPostExecute (che, come la onPreExecute, è eseguita sul thread dell'interfaccia) non verrebbe mai chiamata, forzandoci a ripetere la richiesta di rete e consumare quindi dati aggiuntivi.

Ci sono quindi altri metodi per effettuare una richiesta di rete in maniera asincrona ma, per questa settimana, possiamo fermarci qui, ricapitolando per comodità le API che abbiamo utilizzato:

L'appuntamento è quindi alla prossima settimana con l'applicazione per gli RSS e, prima di salutarvi, vogliamo chiudere la puntata con una domanda: cos'abbiamo volutamente omesso in queste righe? E quale crash comporta questa dimenticanza?