Autore Topic: [facile] utilizzo della libreria android-async-http  (Letto 5144 volte)

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
[facile] utilizzo della libreria android-async-http
« il: 14 Settembre 2013, 10:43:52 CEST »
+3
Livello di difficoltà : facile
Min SDK : 8
Sorgente : ZIP allegato e GIT https://code.google.com/p/it-anddev-bradipao-asyncnetrequest/


Riferimenti

   android asynchronous http client library : Android Asynchronous Http Client
   github repository : https://github.com/loopj/android-async-http
   licenza : Apache License, Version 2.0


Introduzione

Questo è un tutorial di base per l'utilizzo della libreria android-async-http, che consente in modo semplice e immediato di fare richieste http in modo asincrono: dall'activity viene lanciata la richiesta, il client http esegue la richiesta stessa in un thread separato, e alla fine l'activity riceve i dati tramite una funzione callback.

L'esecuzione della connessione di rete in un thread separato è un obbligo della piattaforma android, pena la famigerata NetworkOnMainThreadException, che da qualche versione di android impedisce la compilazione di applicazioni in cui il client di rete vorrebbe effettuare la richiesta di rete nel di interfaccia grafica. Chiunque abbia realizzato un app con accesso alla rete, alla fine ha implementato la connessione in un thread o in un asynctask, probabilmente costruendosi le proprie classi di gestione.

Questa libreria, ben rodata e largamente diffusa, automatizzare e semplifica la gestione delle connessioni di rete in thread separati. E' quindi da prendere in considerazione prima di ricorrere ad implmentazioni personalizzate. La libreria è distribuita sotto licenza Apache-v2, quindi molto permissiva anche verso impieghi commerciali, è infatti attualmente usata da applicazioni molto famose come Instagram e Pinterest.


Importazione della libreria

La preparazione del progetto per l'uso della libreria consiste nello scaricare il JAR  della libreria (android-async-http-1.4.3.jar in questo caso) dal sito Android Asynchronous Http Client e copiarlo nella cartela libs del proprio progetto.


Esempio di utilizzo per richiesta di rete di tipo testo

L'esempio più semplice di utilizzo è l'esecuzione di una richiesta HTTP GET per ricevere del testo, per esempio la pagina web di un sito. A tale scopo è sufficiente creare una istanza di AsyncHttpClient ed usare la funzione get a cui si passano due parametri:

url : indirizzo della pagina web

new AsyncHttpResponseHandler() : è la funzione di callback che sarà eseguita dalla libreria una volta che l'esecuzione della connessione sarà stata terminata. Oltre a crearne una istanza si provvede anche a personalizzare (facciamo un @override) il codice delle funzioni onSuccess (eseguito quando la connessione termina con successo) ed eventualmente onFailure (eseguito quando la connessione fallisce per qualche motivo).

Nel nostro esempio abbiamo collegato l'esecuzione del codice al click su un button, con output in una TextView.

Codice (Java): [Seleziona]
// button btn1 listener
btn1.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
     
      // istanza del client
      AsyncHttpClient client = new AsyncHttpClient();
      // recupero l'url dalla EditText
      String url = et1.getText().toString();
      // eseguo la richiesta get passando url e creando le callback
      client.get(url,new AsyncHttpResponseHandler() {
         // callback chiamata quando la connessione termina con successo
         @Override
         public void onSuccess(String response) {
            tv1.setText("http GET request successful");
            Log.d("AREQ","http GET request successful");
         }
         // callback chiamata quando la connessione fallisce
         @Override
         public void onFailure(Throwable e,String response) {
            tv1.setText("http GET request failed");
            Log.d("AREQ","http GET request failed");
         }
      });

   }
});

Riepilogando, la sequenza degli eventi è questa:
- clic sul bottone
- creazione client
- chiamata della get
- il controllo torna all'activity mentre un thread parallelo esegue la connessione di rete
- quando il thread parallelo termina, nel thread principale viene eseguita la funzione onSuccess o onFailure

Richiesta fallita a sinistra e riuscita a destra :



Esempio di utilizzo per richiesta di rete di tipo binario

L'esempio sopra riportato è il più semplice di tutti, ma ovviamente la libreria supporta tutte le tipologie di richieste HTTP con i vari parametri che possono essere coinvolti. Non ha molto senso provarle tutte nel tutorial, ma visto l'utilizzo ampiamente diffuso, è interessante vedere come può essere eseguita una richiesta HTTP GET di un'immagine (quindi di tipo binario).

Il codice è molto simile al precedente con l'eccezione della callback che è di tipo diverso, in quanto questa volta al posto del testo riceverà dati binari.

Codice (Java): [Seleziona]
// button btn2 listener
btn2.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
     
      // istanza del client
      AsyncHttpClient client = new AsyncHttpClient();
      // recupero l'url dalla EditText
      String url = et1.getText().toString();
      // eseguo la richiesta get passando url e creando le callback
      String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
      client.get(url,new BinaryHttpResponseHandler(allowedContentTypes) {
         // callback chiamata quando la connessione termina con successo
         @Override
         public void onSuccess(byte[] imageData) {
            Bitmap bitmap = BitmapFactory.decodeByteArray(imageData,0,imageData.length);
            iv1.setImageBitmap(bitmap);
            Log.d("AREQ","http IMAGE request successful");
         }
         // callback chiamata quando la connessione fallisce
         @Override
         public void onFailure(Throwable e, byte[] imageData) {
            tv1.setText("http IMAGE request failed");
            Log.d("AREQ","http IMAGE request failed");
         }
      });

   }
});

La sequenza di eventi è del tutto identica alla precedente, la differenza è più che altro strumentale a questo tutorial, visto che una volta ricevuti i dati binari dell'immagine di provvede ad eseguirne la decodifica ed a visualizzare l'immagine nella ImageView.




L'unica nota a margine di quest'ultimo esempio riguarda il processamento dei dati binari ricevuti. In questo caso decodifico l'immagine direttamente nel thread principale, ma se il processamento è molto oneroso dovrebbe essere eseguito a sua volta in un thread separato prima di usarne il risultato.


Tutto il codice

Codice (Java): [Seleziona]
package it.anddev.bradipao.asyncnetrequest;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.BinaryHttpResponseHandler;

public class MainActivity extends Activity {

   // text example URL : http://www.anddev.it
   // image example URL : http://www.android.com/images/whatsnew/jb-new-logo.png
   
   // views
   EditText et1;
   Button btn1,btn2;
   TextView tv1;
   ImageView iv1;
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.ac_main);
     
      // get views
      et1 = (EditText) findViewById(R.id.et1);
      btn1 = (Button) findViewById(R.id.btn1);
      btn2 = (Button) findViewById(R.id.btn2);
      tv1 = (TextView) findViewById(R.id.tv1);
      iv1 = (ImageView) findViewById(R.id.iv1);
     
      // button btn1 listener
      btn1.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
           
            AsyncHttpClient client = new AsyncHttpClient();
            String url = et1.getText().toString();
            client.get(url,new AsyncHttpResponseHandler() {
               @Override
               public void onSuccess(String response) {
                  tv1.setText("http GET request successful");
                  Log.d("AREQ","http GET request successful");
               }
               @Override
               public void onFailure(Throwable e,String response) {
                  tv1.setText("http GET request failed");
                  Log.d("AREQ","http GET request failed");
               }
            });

         }
      });
     
      // button btn2 listener
      btn2.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
           
            AsyncHttpClient client = new AsyncHttpClient();
            String url = et1.getText().toString();
            String[] allowedContentTypes = new String[] { "image/png", "image/jpeg" };
            client.get(url,new BinaryHttpResponseHandler(allowedContentTypes) {
               @Override
               public void onSuccess(byte[] imageData) {
                  Bitmap bitmap = BitmapFactory.decodeByteArray(imageData,0,imageData.length);
                  iv1.setImageBitmap(bitmap);
                  Log.d("AREQ","http IMAGE request successful");
               }
               @Override
               public void onFailure(Throwable e, byte[] imageData) {
                  tv1.setText("http IMAGE request failed");
                  Log.d("AREQ","http IMAGE request failed");
               }
            });

         }
      });
     
   }
   
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

}
« Ultima modifica: 14 Settembre 2013, 11:05:48 CEST da bradipao »
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store