¿Cómo configuro correctamente Volley para descargar imágenes desde una URL
Sé que Volley se supone que hacer la descarga y almacenamiento en caché de imágenes sin sentido simple pero todavía he estado luchando por horas para implementarlo correctamente. He mirado alrededor de la red, así como los muchos artículos sobre stackoverflow con respecto a volea, pero ninguno de los ejemplos que he encontrado parecen funcionar para mí.
Sólo quiero usar volley para descargar y almacenar en caché las imágenes de una url determinada, no para hacer ninguna manipulación de HTTP JSON REST. Sólo para tomar urls determinado, descargar los mapas de bits y establecerlos a la vista de la imagen y luego agregarlos a la caché.
- Android ViewPager: Actualización de fragmentos fuera de la pantalla pero en caché en ViewPager
- ¿Cómo implementar correctamente el feed (similar a Facebook / Instagram) en Android?
- Memoria caché de picasso para Android
- Borrar memoria caché de Picasso
- Cómo evitar un retraso de 15 segundos / caché en Android Media Player al reproducir la secuencia
Este ha sido mi último intento hasta ahora. ¿Cómo carga y cacheo las imágenes con volley correctamente?
if (data.getImageUrl() != null) { try { holder.thumbnail.setTag(data.getImageUrl()); Cache cache = ImgController.getInstance().getRequestQueue().getCache(); Cache.Entry entry = cache.get(data.getImageUrl()); if (entry != null) { try { String cImg = new String(entry.data, "UTF-8"); LruBitmapCache bitmapCache = new LruBitmapCache(); holder.thumbnail.setImageBitmap(bitmapCache.getBitmap(cImg)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else { ImageLoader imageLoader = ImgController.getInstance().getImageLoader(); imageLoader.get(data.getImageUrl(), new ImageListener() { @Override public void onErrorResponse(VolleyError error) { holder.thumbnail.setImageResource(R.drawable.filler_icon); } @Override public void onResponse(ImageLoader.ImageContainer response, boolean arg1) { if (response.getBitmap() != null) { // load image into imageview holder.thumbnail.setImageBitmap(response.getBitmap()); } } }); } return convertView; } catch (Exception e) { e.printStackTrace(); Log.v(DEBUG_TAG, "no image: ", e); holder.thumbnail.setImageResource(R.drawable.filler_icon); } }else { return null; } return convertView; }
Cuando ejecuto esto obtengo una NullPointerException apuntando a esta línea
Cache cache = ImgController.getInstance().getRequestQueue().getCache();
He configurado la siguiente clase singleton para manejar las solicitudes
public class ImgController extends Application { public static final String TAG = ImgController.class.getSimpleName(); private RequestQueue requestQueue; private ImageLoader imageLoader; private static ImgController instance; @Override public void onCreate() { super.onCreate(); instance = this; } public static synchronized ImgController getInstance(){ return instance; } public RequestQueue getRequestQueue(){ if(requestQueue == null){ requestQueue = Volley.newRequestQueue(getApplicationContext()); } return this.requestQueue; } public ImageLoader getImageLoader(){ getRequestQueue(); if(imageLoader == null){ imageLoader = new ImageLoader(this.requestQueue, new LruBitmapCache()); } return this.imageLoader; } public <T> void addToRequestQueue(Request<T> req, String tag) { // set the default tag if tag is empty req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } public <T> void addToRequestQueue(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } public void cancelPendingRequests(Object tag) { if (requestQueue != null) { requestQueue.cancelAll(tag); } }
}
Así como la siguiente clase LruBitmapCache
public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache { public static int getDefaultLruCacheSize(){ final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); final int cacheSize = maxMemory / 8; return cacheSize; } public LruBitmapCache() { this(getDefaultLruCacheSize()); } public LruBitmapCache(int maxSize) { super(maxSize); } @Override public Bitmap getBitmap(String url) { return get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { put (url, bitmap); }
}
- Caché de datos en la preferencia compartida
- ¿Cómo saber OkHttpClient para ignorar la caché y forzar la actualización desde el servidor?
- Obtener imagen uri de picasso?
- Caché HTTP con Retrofit 2.0.x
- Android: Estrategia de caché de imágenes y tamaño de caché de memoria
- Tamaño máximo del caché duro de un ImageDownloader
- Android: cómo borrar caché de aplicaciones y mantener datos de usuario a través de adb?
- Android maps v2 se vuelve de baja calidad cuando el área del mapa se mueve automáticamente
(Lo siento por la mala habilidad inglesa ^^;)
Volley se supone que hacer la descarga y almacenamiento en caché de imágenes sin sentido simple
¡SÍ! Volley es MUY SIMPLE. Usted no necesita pensar en golpe de caché, carga de imágenes, etc …
Sólo use NetworkImageView
. Belows son ejemplo.
Layout_example.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <com.android.volley.toolbox.NetworkImageView android:id="@+id/photo" android:adjustViewBounds="true" android:scaleType="fitCenter" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
MainActivity.java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_example); NetworkImageView nv = (NetworkImageView) findViewById(R.id.photo); nv.setDefaultImageResId(R.drawable.default_image); // image for loading... nv.setImageUrl(imageUrl, ImgController.getInstance().getImageLoader()); //ImgController from your code. }
NetworkImageView
carga automáticamente la imagen de la cola de fondo y cancela la solicitud cuando esta vista se separa using ImageLoader
. Y ImageLoader
utiliza automáticamente caché de memoria lru y caché de disco. NetworkImageView
es la mejor solución para usted.
Información Adicional
NetworkImageView | ImageLoader (uses `LruBitmapCache` you implemented.) | RequestQueue (uses `DiskBasedCache`. it is already implemented in volley.)
Una llamada de retorno para Solicitud de imagen está disponible para Volley, puede utilizar el siguiente código a continuación.
ImageView iv = null; /*Attach the Pointer for ImageView*/ RequestQueue requestAdministrator = null; /*Attach the Pointer for Volley*/ ImageRequest ir = new ImageRequest(url, new Response.Listener<Bitmap>() { @Override public void onResponse(Bitmap response) { // callback iv.setImageBitmap(response); } }, 100, 100, null, null); // 100 is your custom Size before Downloading the Image. requestAdministrator.add(ir);
ImageRequest está obsoleto por lo que lo estoy haciendo de la siguiente manera:
Paso 1: Haga que la clase Application sea la siguiente
public class YourApplicationClass extends Application { private static YourApplicationClass sInstance; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; public static YourApplicationClass getInstance(){ return sInstance; } @Override public void onCreate() { super.onCreate(); sInstance = this; mRequestQueue = Volley.newRequestQueue(this); mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() { private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10); public Bitmap getBitmap(String url) { return mCache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { mCache.put(url, bitmap); } }); } public RequestQueue getRequestQueue(){ return mRequestQueue; } public ImageLoader getImageLoader(){ return mImageLoader; } }
Paso 2: Ahora haga una petición de imagen como sigue de cualquier actividad o fragmento
YourApplicationClass.getInstance().getImageLoader().get(image_url, new ImageLoader.ImageListener() { @Override public void onResponse(ImageLoader.ImageContainer imageContainer, boolean b) { Bitmap bitmap = imageContainer.getBitmap(); //use bitmap } @Override public void onErrorResponse(VolleyError volleyError) { } });
Esto está cubierto en la documentación: https://developer.android.com/training/volley/request.html#request-image
Tengo una solución más simple para mostrar la imagen de url y almacenarla en caché. Sin agregar clases adicionales, sólo MainActivity. Probablemente ayudará a alguien …
Aquí está mi XML que muestra sólo ImageView
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.natalie.volley.MainActivity"> <ImageView android:id="@+id/ivImageView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="50dp"/> </android.support.constraint.ConstraintLayout>
Y aquí está mi MainAvtivity.java:
import android.graphics.Bitmap; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ImageView; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.ImageRequest; import com.android.volley.toolbox.Volley; public class MainActivity extends AppCompatActivity { private String url = "http://kingofwallpapers.com/picture/picture-010.jpg"; ImageView ivImageView; RequestQueue mRequestQueue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ivImageView = (ImageView)findViewById(R.id.ivImageView); mRequestQueue = Volley.newRequestQueue(this.getApplicationContext()); ImageRequest imageRequest = new ImageRequest(url, new BitmapListener(), 0, 0, null, null, new MyErrorListener()); mRequestQueue.add(imageRequest); } private class BitmapListener implements Response.Listener<Bitmap> { @Override public void onResponse(Bitmap response) { // response = your url's bitmap ivImageView.setImageBitmap(response); } } private class MyErrorListener implements Response.ErrorListener { @Override public void onErrorResponse(VolleyError error) { //store a default image if connection failed ivImageView.setImageResource(R.drawable.error_icon); } } }
No olvides añadir <uses-permission android:name="android.permission.INTERNET" />
en Manifest.xml y compile 'com.android.volley:volley:1.0.0'
en las dependencias de build.gradle
- Configurar ImageView ScaleType en "center" no funciona como espero
- Cómo hacer que el diseño de Android sea proporcional independientemente del tamaño de la pantalla y la orientación