studio - Almacenamiento en caché de imágenes de Android
para que sirve la libreria picasso en android studio (17)
¿Cómo puedo almacenar en caché las imágenes después de que se descargan de la web?
Última respuesta, pero pensé que debería agregar un enlace a mi sitio porque he escrito un tutorial sobre cómo crear una memoria caché de imágenes para Android: http://squarewolf.nl/2010/11/android-image-cache/ Actualización: el la página se ha desconectado porque la fuente no está actualizada. Me uno a @elenasys en su consejo para usar https://github.com/kaeppler/ignition .
Entonces, a todas las personas que tropiezan con esta pregunta y no han encontrado una solución: ¡espero que disfruten! = D
Como Thunder Rabbit sugirió, ImageDownloader es el mejor para el trabajo. También encontré una pequeña variación de la clase en:
http://theandroidcoder.com/utilities/android-image-download-and-caching/
La diferencia principal entre los dos es que ImageDownloader utiliza el sistema de almacenamiento en caché de Android, y el modificado utiliza el almacenamiento interno y externo como almacenamiento en caché, manteniendo las imágenes en caché de forma indefinida o hasta que el usuario lo elimine manualmente. El autor también menciona compatibilidad con Android 2.1.
Consideraría usar el caché de imágenes de droidfu. Implementa una caché de imágenes en memoria y en disco. También obtienes un WebImageView que aprovecha la biblioteca de ImageCache.
Aquí está la descripción completa de droidfu y WebImageView: http://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/
Considere usar la biblioteca de Universal Image Loader por Sergey Tarasevich . Viene con:
- Carga de imágenes multiproceso. Le permite definir el tamaño del grupo de subprocesos
- Almacenamiento en caché de imágenes en la memoria, en el sistema de archivos del dispositivo y en la tarjeta SD.
- Posibilidad de escuchar el progreso de carga y carga de eventos
Universal Image Loader permite una gestión detallada del caché para las imágenes descargadas, con las siguientes configuraciones de caché:
-
UsingFreqLimitedMemoryCache
: el mapa de bits menos utilizado se elimina cuando se excede el límite de tamaño de caché. -
LRULimitedMemoryCache
: el mapa de bits utilizado menos recientemente se elimina cuando se excede el límite de tamaño de caché. -
FIFOLimitedMemoryCache
: la regla FIFO se utiliza para eliminación cuando se excede el límite de tamaño de caché. -
LargestLimitedMemoryCache
: el mapa de bits más grande se elimina cuando se excede el límite de tamaño de caché. -
LimitedAgeMemoryCache
: el objeto en caché se elimina cuando su antigüedad excede el valor definido . -
WeakMemoryCache
: memoria caché con solo referencias débiles a bitmaps.
Un simple ejemplo de uso:
ImageView imageView = groupView.findViewById(R.id.imageView);
String imageUrl = "http://site.com/image.png";
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);
Este ejemplo utiliza el valor predeterminado UsingFreqLimitedMemoryCache
.
Conviértelos en mapas de bits y guárdelos en una colección (HashMap, lista, etc.) o puede escribirlos en la tarjeta SD.
Al almacenarlos en el espacio de la aplicación utilizando el primer enfoque, es posible que desee envolverlos alrededor de java.lang.ref.SoftReference específicamente si sus números son grandes (para que sean basura recolectada durante una crisis). Esto podría seguir una recarga, sin embargo.
HashMap<String,SoftReference<Bitmap>> imageCache =
new HashMap<String,SoftReference<Bitmap>>();
escribirlos en SDcard no requerirá una recarga; solo un permiso de usuario.
En cuanto a la elegante solución connection.setUseCaches
anterior: lamentablemente, no funcionará sin un esfuerzo adicional. Necesitará instalar un ResponseCache
usando ResponseCache.setDefault
. De lo contrario, HttpURLConnection
ignorará silenciosamente el setUseCaches(true)
.
Vea los comentarios en la parte superior de FileResponseCache.java
para más detalles:
(Publicaría esto en un comentario, pero aparentemente no tengo suficiente karma SO.)
Esta es una buena captura de Joe. El ejemplo de código anterior tiene dos problemas, uno: el objeto de respuesta no es una instancia de mapa de bits (cuando mi URL hace referencia a un jpg, como http: / website.com / image.jpg, es un
org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream).
En segundo lugar, como señala Joe, no se produce el almacenamiento en caché sin la configuración de un caché de respuesta. Los desarrolladores de Android tienen que rodar su propio caché. Aquí hay un ejemplo para hacerlo, pero solo se almacena en la memoria caché, lo que realmente no es la solución completa.
http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/
La API de caché URLConnection se describe aquí:
http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html
Sigo pensando que esta es una solución correcta para seguir esta ruta, pero aún tienes que escribir un caché. Suena divertido, pero prefiero escribir características.
Había estado luchando con esto por un tiempo; las respuestas usando SoftReferences perderían sus datos demasiado rápido. Las respuestas que sugieren la creación de una RequestCache eran demasiado desordenadas, además de que nunca pude encontrar un ejemplo completo.
Pero ImageDownloader.java funciona maravillosamente para mí. Utiliza un HashMap hasta que se alcanza la capacidad o hasta que se agota el tiempo de espera de purga, luego las cosas se mueven a una referencia suave, utilizando de ese modo lo mejor de ambos mundos.
Hay una entrada especial en la sección de entrenamiento oficial de Android sobre esto: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
La sección es bastante nueva, no estaba allí cuando se hizo la pregunta.
La solución sugerida es usar un LruCache. Esa clase se introdujo en Honeycomb, pero también se incluye en la biblioteca de compatibilidad.
Puede inicializar un LruCache estableciendo el número máximo de entradas y las clasificará automáticamente y las borrará menos usadas cuando sobrepase el límite. Aparte de eso, se usa como un mapa normal.
El código de muestra de la página oficial:
private LruCache mMemoryCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final int memClass = ((ActivityManager) context.getSystemService(
Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;
mMemoryCache = new LruCache(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in bytes rather than number of items.
return bitmap.getByteCount();
}
};
...
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
Anteriormente, SoftReferences era una buena alternativa, pero ya no, citando de la página oficial:
Nota: En el pasado, una implementación de memoria caché popular era una memoria caché de mapas de bits de referencia blanda o de referencia débil, sin embargo, esto no es recomendable. A partir de Android 2.3 (Nivel 9 de la API), el recolector de basura es más agresivo al recopilar referencias débiles / débiles, lo que las hace bastante ineficaces. Además, antes de Android 3.0 (API nivel 11), los datos de respaldo de un mapa de bits se almacenaron en la memoria nativa, que no se publica de manera predecible, lo que puede causar que una aplicación exceda brevemente sus límites de memoria y falle.
Incluso una respuesta más tardía, pero escribí un Administrador de imágenes de Android que maneja el almacenamiento en caché de forma transparente (memoria y disco). El código está en Github github.com/felipecsl/Android-ImageManager
Libs-for-android de Google tiene unas buenas bibliotecas para administrar la imagen y el caché de archivos.
Lo que realmente funcionó para mí fue configurar ResponseCache en mi clase principal:
try {
File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) { }
y
connection.setUseCaches(true);
al descargar mapa de bits.
http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html
Para descargar una imagen y guardarla en la tarjeta de memoria, puede hacerlo así.
//First create a new URL object
URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif")
//Next create a file, the example below will save to the SDCARD using JPEG format
File file = new File("/sdcard/example.jpg");
//Next create a Bitmap object and download the image to bitmap
Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
//Finally compress the bitmap, saving to the file previously created
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));
No olvides agregar el permiso de Internet a tu manifiesto:
<uses-permission android:name="android.permission.INTERNET" />
Probé SoftReferences, son reclamados de manera tan agresiva en Android que sentí que no tenía sentido usarlos
Sugiero IGNITION esto es incluso mejor que Droid fu
https://github.com/kaeppler/ignition
https://github.com/kaeppler/ignition/wiki/Sample-applications
Use LruCache
para almacenar en caché las imágenes de manera eficiente. Puedes leer sobre LruCache
del sitio para desarrolladores de Android
He utilizado la siguiente solución para la descarga de imágenes y el almacenamiento en caché en Android. Puedes seguir los pasos a continuación:
PASO 1: haga una clase llamada ImagesCache
. He usado el Singleton object for this class
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
public class ImagesCache
{
private LruCache<String, Bitmap> imagesWarehouse;
private static ImagesCache cache;
public static ImagesCache getInstance()
{
if(cache == null)
{
cache = new ImagesCache();
}
return cache;
}
public void initializeCache()
{
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /1024);
final int cacheSize = maxMemory / 8;
System.out.println("cache size = "+cacheSize);
imagesWarehouse = new LruCache<String, Bitmap>(cacheSize)
{
protected int sizeOf(String key, Bitmap value)
{
// The cache size will be measured in kilobytes rather than number of items.
int bitmapByteCount = value.getRowBytes() * value.getHeight();
return bitmapByteCount / 1024;
}
};
}
public void addImageToWarehouse(String key, Bitmap value)
{
if(imagesWarehouse != null && imagesWarehouse.get(key) == null)
{
imagesWarehouse.put(key, value);
}
}
public Bitmap getImageFromWarehouse(String key)
{
if(key != null)
{
return imagesWarehouse.get(key);
}
else
{
return null;
}
}
public void removeImageFromWarehouse(String key)
{
imagesWarehouse.remove(key);
}
public void clearCache()
{
if(imagesWarehouse != null)
{
imagesWarehouse.evictAll();
}
}
}
PASO 2:
hacer otra clase llamada DownloadImageTask que se utiliza si el mapa de bits no está disponible en la memoria caché lo descargará desde aquí:
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
{
private int inSampleSize = 0;
private String imageUrl;
private BaseAdapter adapter;
private ImagesCache cache;
private int desiredWidth, desiredHeight;
private Bitmap image = null;
private ImageView ivImageView;
public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight)
{
this.adapter = adapter;
this.cache = ImagesCache.getInstance();
this.desiredWidth = desiredWidth;
this.desiredHeight = desiredHeight;
}
public DownloadImageTask(ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight)
{
this.cache = cache;
this.ivImageView = ivImageView;
this.desiredHeight = desireHeight;
this.desiredWidth = desireWidth;
}
@Override
protected Bitmap doInBackground(String... params)
{
imageUrl = params[0];
return getImage(imageUrl);
}
@Override
protected void onPostExecute(Bitmap result)
{
super.onPostExecute(result);
if(result != null)
{
cache.addImageToWarehouse(imageUrl, result);
if(ivImageView != null)
{
ivImageView.setImageBitmap(result);
}
else
{
}
if(adapter != null)
{
adapter.notifyDataSetChanged();
}
}
}
private Bitmap getImage(String imageUrl)
{
if(cache.getImageFromWarehouse(imageUrl) == null)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = inSampleSize;
try
{
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
InputStream stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
if(imageWidth > desiredWidth || imageHeight > desiredHeight)
{
System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);
inSampleSize = inSampleSize + 2;
getImage(imageUrl);
}
else
{
options.inJustDecodeBounds = false;
connection = (HttpURLConnection)url.openConnection();
stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
return image;
}
}
catch(Exception e)
{
Log.e("getImage", e.toString());
}
}
return image;
}
PASO 3: Uso de su Activity
o Adapter
Nota: si desea cargar imágenes desde la URL de Activity
Class. Use el segundo Constructor de DownloadImageTask
, pero si desea visualizar la imagen desde el Adapter
use primero el Constructor de DownloadImageTask
(por ejemplo, tiene una imagen en ListView
y está configurando una imagen desde ''Adaptador'')
USO DE LA ACTIVIDAD:
ImageView imv = (ImageView) findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();//Singleton instance handled in ImagesCache class.
cache.initializeCache();
String img = "your_image_url_here";
Bitmap bm = cache.getImageFromWarehouse(img);
if(bm != null)
{
imv.setImageBitmap(bm);
}
else
{
imv.setImageBitmap(null);
DownloadImageTask imgTask = new DownloadImageTask(cache, imv, 300, 300);//Since you are using it from `Activity` call second Constructor.
imgTask.execute(img);
}
USO DEL ADAPTADOR:
ImageView imv = (ImageView) rowView.findViewById(R.id.imageView);
ImagesCache cache = ImagesCache.getInstance();
cache.initializeCache();
String img = "your_image_url_here";
Bitmap bm = cache.getImageFromWarehouse(img);
if(bm != null)
{
imv.setImageBitmap(bm);
}
else
{
imv.setImageBitmap(null);
DownloadImageTask imgTask = new DownloadImageTask(this, 300, 300);//Since you are using it from `Adapter` call first Constructor.
imgTask.execute(img);
}
Nota:
cache.initializeCache()
puede usar esta declaración en la primera Actividad de su aplicación. Una vez que hayas inicializado la caché, nunca necesitarás inicializarla cada vez que ImagesCache
instancia de ImagesCache
.
Nunca soy bueno para explicar cosas, pero espero que esto ayude a los principiantes a cómo almacenar en caché usando LruCache
y su uso :)
EDITAR:
Hoy en día existen bibliotecas muy famosas conocidas como Picasso
y Glide
que se pueden utilizar para cargar imágenes de manera muy eficiente en la aplicación de Android. Prueba esta biblioteca muy simple y útil Picasso para Android y Glide para Android . No necesita preocuparse por las imágenes de caché.
Picasso permite cargar imágenes sin inconvenientes en su aplicación, ¡a menudo en una línea de código!
Glide, al igual que Picasso, puede cargar y mostrar imágenes de muchas fuentes, a la vez que se ocupa del almacenamiento en caché y mantiene un bajo impacto de memoria al realizar manipulaciones de imágenes. Ha sido utilizado por las aplicaciones oficiales de Google (como la aplicación para Google I / O 2015) y es tan popular como Picasso. En esta serie, vamos a explorar las diferencias y las ventajas de Glide sobre Picasso.
También puedes visitar el blog para ver la diferencia entre Glide y Picasso
Y ahora la frase clave: use la memoria caché del sistema.
URL url = new URL(strUrl);
URLConnection connection = url.openConnection();
connection.setUseCaches(true);
Object response = connection.getContent();
if (response instanceof Bitmap) {
Bitmap bitmap = (Bitmap)response;
}
Proporciona memoria y caché flash-rom, compartida con el navegador.
Grr. Ojalá alguien me hubiera dicho que antes de escribir mi propio administrador de caché.