2013-05-22 14 views
34

Ho problemi nell'implementazione della cache di immagini utilizzando la nuova libreria di Volley. Nella presentazione, il codice simile a questaAndroid Volley ImageLoader - Parametro BitmapLruCache?

mRequestQueue = Volley.newRequestQueue(context); 
mImageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache()); 

La BitmapLruCache non è, ovviamente, incluso nel kit di strumenti. Qualche idea su come implementarlo o indicarmi alcune risorse?

http://www.youtube.com/watch?v=yhv8l9F44qo @ 14: 38

Grazie!

risposta

48
import android.graphics.Bitmap; 
import android.support.v4.util.LruCache; 

public class BitmapLruCache extends LruCache<String, Bitmap> implements ImageCache { 
    public static int getDefaultLruCacheSize() { 
     final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
     final int cacheSize = maxMemory/8; 

     return cacheSize; 
    } 

    public BitmapLruCache() { 
     this(getDefaultLruCacheSize()); 
    } 

    public BitmapLruCache(int sizeInKiloBytes) { 
     super(sizeInKiloBytes); 
    } 

    @Override 
    protected int sizeOf(String key, Bitmap value) { 
     return value.getRowBytes() * value.getHeight()/1024; 
    } 

    @Override 
    public Bitmap getBitmap(String url) { 
     return get(url); 
    } 

    @Override 
    public void putBitmap(String url, Bitmap bitmap) { 
     put(url, bitmap); 
    } 
} 
+0

Grazie mille, tra l'altro, come si fa a determinare la dimensione corretta della cache? parla di come funzioni una dimensione dello schermo, sembra logico, ma come posso renderlo più preciso? – urSus

+0

@Valasto Benny Lava, non sono sicuro, ma qualcosa come 'N * screen_width * screen_height' con' N ~ 10' sembra logico per me. –

+0

perché ora ciò che accade funziona bene, ma l'immagine si carica di nuovo se esce dallo schermo e ritorna, quindi presumo che sia stato estratto dalla cache di memoria giusto? Qualche idea di cosa potrebbe essere? – urSus

1

Quello che vi consiglio è utilizzare un Singleton Bitmap Cache in modo da questa cache sarà a disposizione durante tutta la vita della vostra applicazione.

public class BitmapCache implements ImageCache { 
    private LruCache<String, Bitmap> mMemoryCache; 

    private static BitmapCache mInstance; 

    private BitmapCache(Context ctx) { 
     final int memClass = ((ActivityManager) ctx 
       .getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); 
     // Use 1/16th of the available memory for this memory cache. 
     final int cacheSize = 1024 * 1024 * memClass/16; 
     mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
      @Override 
      protected int sizeOf(String key, Bitmap value) { 
       return value.getRowBytes() * value.getHeight(); 
      } 
     }; 
    } 

    public static BitmapCache getInstance(Context ctx) { 
     if (mInstance == null) { 
      mInstance = new BitmapCache(ctx); 
     } 
     return mInstance; 
    } 

    @Override 
    public Bitmap getBitmap(String url) { 
     return mMemoryCache.get(url); 
    } 

    @Override 
    public void putBitmap(String url, Bitmap bitmap) { 
     mMemoryCache.put(url, bitmap); 
    } 
} 
5

Ecco un esempio di utilizzo di un disco di base della cache LRU con Volley. Si basa sull'utilizzo di una versione di DiskLruCache di AOSP gestita da Jake Wharton. http://blogs.captechconsulting.com/blog/raymond-robinson/google-io-2013-volley-image-cache-tutorial

Modifica: Ho aggiornato il progetto per includere una cache LRU in memoria come implementazione predefinita in quanto questo è il metodo consigliato. Volley gestisce implicitamente la cache basata su disco nella propria cache L2. La cache dell'immagine è solo la cache L1. Ho aggiornato il post originale e aggiunto ulteriori dettagli qui: http://www.thekeyconsultant.com/2013/06/update-volley-image-cache.html.

+1

Nella libreria, sembra che tu stia utilizzando url.hashCode() per generare la chiave richiesta dalla cache del disco. È davvero sicuro? hashCodes non è univoco, quindi non rischierai di ottenere risultati di cache falsi per gli URL che si risolvono in modo casuale sullo stesso codice hash? Ho visto altri che usano MD5 per ridurre il rischio di collisioni, alcuni addirittura forniscono la loro implementazione MD5 per evitare la classe MessageDigest di Androids non-threadsafe. Qualche suggerimento su questo (potenziale) problema? –

+1

Hai ragione, questo è stato appena messo in atto per la demo e funziona la maggior parte del tempo. Sto testando la velocità di UUID.fromString() come alternativa valida. – rdrobinson3

0

questo è disponibile in nuove API per gestire l'OOM

public class BitmapMemCache extends LruCache<string, Bitmap> implements ImageCache { 

    public BitmapMemCache() { 
     this((int) (Runtime.getRuntime().maxMemory()/1024)/8); 
    } 

    public BitmapMemCache(int sizeInKiloBytes) { 
     super(sizeInKiloBytes); 
    } 

    @Override 
    protected int sizeOf(String key, Bitmap bitmap) { 
     int size = bitmap.getByteCount()/1024; 
     return size; 
    } 

    public boolean contains(String key) { 
     return get(key) != null; 
    } 

    public Bitmap getBitmap(String key) { 
     Bitmap bitmap = get(key); 
     return bitmap; 
    } 

    public void putBitmap(String url, Bitmap bitmap) { 
     put(url, bitmap); 
    } 
}