- Descargar imagenes con Volley

Disponemos de varias alternativas para descargar imágenes con Volley. La primera consiste en usar el método ImageRequest() que trabaja de forma similar al mostrado en el apartado anterior:

ImageRequest peticion = new ImageRequest(
      "http://mmoviles.upv.es/img/moviles.png",
      new Response.Listener<Bitmap>() {
         @Override
         public void onResponse(Bitmap bitmap) {
            miImageView.setImageBitmap(bitmap);
         }
      }, 0, 0, null, // maxWidth, maxHeight, decodeConfig
      new Response.ErrorListener() {
         @Override
         public void onErrorResponse(VolleyError error) {
            miImageView.setImage Resource(R.drawable.error_carga);
         }
      }
);
colaPeticiones.add(peticion);

Observa como este método tiene tres parámetros adicionales, donde podemos configurar como se va a decodificar la imagen. Se utilizan los valores por defecto, para más información consultar la documentación oficial.

Cuando queremos descargar múltiples imágenes de forma simultánea se recomienda usar la clase ImageLoader. La principal diferencia con el método anterior es que las imágenes se guardan en una caché en memoria, en lugar de en disco. Esto agiliza mucho el proceso y evita molestos parpadeos de las imágenes.

 El primer paso va a consistir en crear una instancia de ImageLoader:

RequestQueue colaPeticiones = Volley.newRequestQueue(this);
ImageLoader lectorImagenes = new ImageLoader(colaPeticiones,
   new ImageLoader.ImageCache() {
      private final LruCache<String, Bitmap> cache = new LruCache<String,
                                                             Bitmap>(10);
      public void putBitmap(String url, Bitmap bitmap) {
         cache.put(url, bitmap);
      }
      public Bitmap getBitmap(String url) {
        return cache.get(url);
      }
});

Como puedes ver un ImageLoader ha de estar asociado a un RequestQueue. Además ha de definir como se gestiona la caché, por medio de un objeto ImageCache.  En este objeto se define una estructura LruCache para almacenar en memoria pares de URL-Bitmaps. El valor 10, indica en máximo de elementos que queremos almacenar. Además, se definen dos métodos que permiten almacenar y recuperar elementos de la cahé.

Resulta interesante declarar un solo ImageLoader y RequestQueue en toda la aplicación. Como hemos comentado en el apartado anterior, un buen sitio para hacerlo es en la clase Application o en un Singleton.

Usar el ImageLoader es muy sencillo. No tienes más que llamar al método get() e indicarle la URL y un escuchador:

lectorImagenes.get("http://mmoviles.upv.es/img/moviles.png",
       ImageLoader.getImageListener(miImageView, R.drawable.por_defecto,
                                                 R.drawable.error_carga));

El escuchador será llamado cuando se descargue el BitMap y lo asignará al ImageView indicado. También se indican dos recursos que será asignados antes de la carga o en caso de error.

Disponemos de una tercera alternativa que consiste en usar la vista NetworkImageView, definida en Volley para trabajar conjuntamente con un ImageLoader. La nueva vista reemplazaría a ImageView, pero incorpora la posibilidad de cargar la imagen desde una URL. Trabajar con esta vista tiene la ventaja de que la descarga se puede sincronizar con la visualización: cuando la vista va a verse se puede iniciar la descarga y cuando deja de verse se puede cancelar la descarga.

Para usar esta alternativa reemplaza en un layout la etiqueta ImageView por la siguiente, dejando los atributos igual:

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/icono"
    android:layout_width=" match_parent"
    android:layout_height="match_parent"
    …"/>

Para asociar la URL utiliza el siguiente código:

icono = (NetworkImageView)itemView.findViewById(R.id.icono);
icono.setImageUrl("http://mmoviles.upv.es/img/moviles.png", lectorImagenes);

 

Ejercicio: Cargar imágenes de un RecyclerView con Volley

Cuando se trabaja con una lista generada con RecyclerViewes muy frecuente que cada elemento contenga una imagen que ha de descargarse de una URL. Se van a realizar múltiples peticiones simultáneas, por lo que, en este caso donde se recomienda el uso de ImageLoader.

1.    Abre el proyecto Asteroides y añade al fichero Gradle Scripts/Bulid.gradle (Module:app) la dependencia: compile 'com.android.volley:volley:1.0.0'.

2.    En la clase MainActivitydeclara las variables:

public static RequestQueue colaPeticiones;
public static ImageLoader lectorImagenes;

3.    En el método onCreate()inicializa estas variables como se acaba de ver. Recuerda que ya están declarados globalmente y has de quitar la clase antes del nombre del objeto.

4.    En la clase MiAdaptadordentro de onBindViewHolder()comenta el código:

switch (Math.round((float)Math.random()*3)){
    case 0:
        holder.icon.setImageResource(R.drawable.asteroide1);
        break;
    …
}

y reemplázalo por:

MainActivity.lectorImagenes.get("http://mmoviles.upv.es/img/moviles.png",
        ImageLoader.getImageListener(holder.icon, R.drawable.asteroide1,
                                                  R.drawable.asteroide3));

5.    Verifica el funcionamiento.

 

Ejercicio: Cargar imágenes de un RecyclerView con NetworkImageView

En el ejercicio anterior, hemos trabajando con vistas ImageView. En este ejercicio, vamos a reemplazarlas por NetworkImageView. De esta forma la gestión de la descarga puede sincronizarse con la visualización, obteniendo unos resultados óptimos.

1.   Edita el layout elemento_lista.xml reemplazando el <ImageView…  por <com.android.volley.toolbox.NetworkImageView….

2.   En la clase MiAdaptador, dentro de la clase  ViewHolder, reemplaza las dos apariciones de ImageView  por NetworkImageView.

3.   En la clase MiAdaptador, dentro de onBindViewHolder(), comenta el código introducido en el apartado anterior y reemplázalo por:

holder.icon.setImageUrl("http://mmoviles.upv.es/img/moviles.png",
                        MainActivity.lectorImagenes);

4.   Verifica el resultado.