* R AMAN K AZHAMIAKIN O SCAR Z G IOVANNI D E ITT M. B UONARROTI, T RENTO A NDROID D EVELOPMENT C ONCORRENZA
* * 1.Scenari di concorrenza 1.Soluzioni: ●Servizi (accenni) ●Threads ●AsyncTask 1.JSON 1.Gestione HTTP 2.ESERCIZIO CON TWITTER! Sommario
* * Cos’è un thread? Possiamo pensare un thread come un flusso di esecuzione. Il classico processo è un flusso di esecuzione di un dato codice, ovvero un insieme di istruzioni macchina. Java è multi-threading: un processo è costituito da più thread, ovvero più flussi di esecuzione, che possono virtualmente procedere indipendentemente e parallelamente. Introduzione
* * Ci sono scenari in cui abbiamo bisogno di eseguire operazioni contemporaneamente. Ci sono diverse soluzioni, adatte a casi differenti. Operazioni in background che non richiedono un’interfaccia grafica e/o l’interazione dell’utente. Esempi: gestire le reti, sincronizzare I dati, suonare musica, leggere e scrivere files, interagire con content provider. Si usano i Servizi. Operazioni lunghe durante l’utilizzo di un’interfaccia grafica e/o con l’interazione dell’utente. Esempi: fare un calcolo ‘pesante’, ottenere e visualizzare qualcosa da Internet, etc. Si usano i Thread o AsyncTask Multithreading/tasking in Android: quando serve?
* * Operazioni in background che non richiedono un’interfaccia grafica e/o l’interazione dell’utente Un Service è un componente di un’app che può fare operazioni di lunga esecuzione in background e non fornisce un’interfaccia utente. Un diverso componente dell’app può far partire un servizio che continuerà a girare in background anche se l’utente passa ad un’altra applicazione. Oltre a questo un componente può collegarsi ad un servizio, interagire con esso e svolgere operazioni. Servizi possono essere utilizzati anche dalle altre app! Concorrenza: Servizi
* * Operazioni lunghe durante l’utilizzo di un’interfaccia grafica e/o con l’interazione dell’utente Android gestisce l’interfaccia in un singolo main thread. Il sistema raccoglie tutti gli eventi in una coda e li processa. Tutto il codice di una app viene eseguito nel main thread, ogni istruzione dopo l’altra. Se si fa un’operazione lunga l’app si ferma finché l’operazione non è finita. Per avere una buona esperienza utente tutti i processi potenzialmente lenti dovrebbero essere eseguiti in modo asincrono. In alcuni casi Android ci costringe a effettuare operazioni asincrone. Esempi: accesso a Internet, lettura/scrittura in file e db, calcoli complessi. Il sistema Android se una activity non reagisce all’azione dell’utente entro 5 secondi mostra un dialog “Application not responding”. che ci permette di attendere o chiudere l’applicazione. Concorrenza #2
* * Android supporta il package Java java.util.concurrent per eseguire operazioni in background creando altri thread. Concorrenza: Threads Ci sono però degli svantaggi, come: ●La sincronizzazione con il main thread se si restituiscono dei risultati che influenzano l’interfaccia utente ●Non c’è un comportamento di default per annullare i thread ●Non c’è un comportamento di default per gestire i cambiamenti di configurazione di Android Infatti questo codice viola la regola per la quale non si interagisce con gli elementi dell’interfaccia fuori dal main thread! public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork(" mImageView.setImageBitmap(b); } }).start(); }
* * Ci sono dei metodi che ci aiutano, es: ●Activity.runOnUiThread(Runnable) ●View.post(Runnable) ●View.postDelayed(Runnable, long) Concorrenza: Threads #2 public void onClick(View v) { new Thread(new Runnable() { public void run() { final Bitmap bitmap = loadImageFromNetwork(" mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); } C’è una soluzione più elegante: usiamo AsyncTask!
* * La classe AsyncTask incorpora la creazione di processi in background e la sincronizzazione con il main thread. Supporta anche la lettura dei progressi del task in esecuzione. Concorrenza: AsyncTask public void onClick(View v) { new DownloadImageTask().execute(" } private class DownloadImageTask extends AsyncTask { /** Il sistema invoca questo metodo passando i parametri * immessi in.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** Il sistema invoca questo metodo per eseguire ciò che ci serve * nella UI, passando il risultato di doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); }
* * ●Creare una sottoclasse di AsyncTask; ●implementare il metodo doInBackground() che verrà eseguito come thread in background. ●Per aggiornare la UI bisogna implementare onPostExecute() che ottiene il risultato di doInBackground() ed è eseguito nel thread della UI, così si può aggiornare semplicemente. ●Puoi eseguire questo task con il metodo execute() dal thread dell’UI. Ci sono anche altri metodi utili! onPreExecute() operazioni da fare PRIMA di doInBackground() onProgressUpdate() informazioni ottenibili DURANTE l’esecuzione di doInBackground() (es. possiamo calcolare la percentuale di caricamento) Nota bene: in doInBackground() non si accede ad elementi della UI! Concorrenza: AsyncTask #2
* * JSON (JavaScript Object Notation) è un formato per lo scambio di dati. È un sottoinsieme delle specifiche di JavaScript Specification (ECME-Script) ed è da esso direttamente supportato. Android include le librerie di json.org. Le strutture dati in JSON sono basate su coppie chiave/valore. La chiave è una stringa mentre il valore può essere numerico, booleano, stringa o un oggetto. Un oggetto JSON è un insieme di coppie chiave/valore racchiuse in "{" e "}". Le liste (array) sono uno o più valori racchiusi in “[“ e “]” e separati da ",". JSON { firstName: 'Tizio', lastName: 'Caio', address: { street: 'Via Esempio', number: '123' } } [ { firstName: 'Larry', lastName: 'Page' }, { firstName: 'Sergey', lastName: 'Brin' } ]
* * Esempi: leggiamo un oggetto e un array JSON. JSON #2 String json = "["; json += "{ firstName: 'Larry', lastName: 'Page' }"; json += ","; json += "{ firstName: 'Sergey',lastName: 'Brin' }"; json += "]"; JSONArray jsonArray = new JSONArray(json); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String firstName = jsonObject.getString("firstName")); } String json = "{ name: 'Balotelli', number: 45 }"; JSONObject jsonObject = new JSONObject(json); int number = jsonObject.getInt("number"));
* * Android mette a disposizione due package per la gestione della rete : ●java.net.* ○Piu’ verbosa e difficile da configurare, ma questo comporta anche una maggiore flessibilita’ e piu’ controllo. ANDROID E HTTP
* * ●org.apache.http.* ○Piu’ ad alto livello quindi piu’ semplice, minore configurabilita’ Possono essere usate entrambe a seconda dello scopo ma, anche se e’ la prima quella su cui Google investe, noi suggeriamo di usare la seconda per degli utilizzi base. Secondo voi, dove devono essere usate le classi di questi packages? ANDROID E HTTP
* * IN UN ALTRO THREAD! ANDROID E HTTP
* * String dati=”?param1=”+param1+”¶m2=”+param2; URL url = new URL(" HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setReadTimeout(10000); conn.setConnectTimeout(15000); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); //Altri parametri conn.connect(); ESEMPIO richiesta GET con java.net.*
* * Si toglie la stringa coi dati dall’esempio precedente. Si aggiunge: List params = new ArrayList (); params.add(new BasicNameValuePair("firstParam", paramValue1)); params.add(new BasicNameValuePair("secondParam", paramValue2)); params.add(new BasicNameValuePair("thirdParam", paramValue3)); OutputStream os = conn.getOutputStream(); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(os, "UTF-8")); writer.write(getQuery(params)); writer.flush(); writer.close(); os.close(); ESEMPIO richiesta POST con java.net.*
* * HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(" try { List nameValuePairs = new ArrayList (2); nameValuePairs.add(new BasicNameValuePair("id", "12345")); nameValuePairs.add(new BasicNameValuePair("data", "asd")); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); } catch (ClientProtocolException e) {} catch (IOException e) { } ESEMPIO richiesta POST con org.apache.http.*
* * una richiesta di tipo get come si fara’? richiesta con org.apache.http.*
* * HttpClient httpclient = new DefaultHttpClient(); String dati=”?param1=”+param1+”¶m2=”+param2; HttpGet httpg = new HttpGet(" try { HttpResponse response = httpclient.execute(httpg); String res = EntityUtils.toString(resp.getEntity()); } catch (ClientProtocolException e) {} catch (IOException e) {} ESEMPIO richiesta GET con org.apache.http.*
* * Esercizi -Fare chiamate dirette -Usare Threads -Usare altri servizi Web: mat=json&num_of_days=5&key=kgy5kbvrpfqnjkk4atyyqyz6 docs: -Usare altri servizi Web: dati territoriali SmartCampus docs: