2013-05-22 11 views
34

Ich habe Probleme beim Implementieren von Image-Cache mit der neuen Volley-Bibliothek. In der Präsentation aussehen Code wie dieseAndroid Volley ImageLoader - BitmapLruCache Parameter?

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

Die BitmapLruCache ist offensichtlich nicht im Toolkit enthalten. Irgendeine Idee, wie man es umsetzt oder auf einige Ressourcen zeigt?

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

Dank!

Antwort

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

Dank viel, nebenbei zu handhaben, wie Sie die richtige Größe des Caches bestimmen? er spricht davon, dass es eine Funktion der Bildschirmgröße ist, scheint logisch, aber wie mache ich es genauer? – urSus

+0

@Vlasto Benny Lava, ich bin mir nicht sicher, aber etwas wie 'N * screen_width * screen_height' mit' N ~ 10' scheint logisch für mich. –

+0

weil jetzt was passiert ist funktioniert gut, aber Bild lädt wieder, wenn es aus dem Bildschirm geht und kommt zurück, so nehme ich an, es wurde aus dem Cache-Speicher geworfen richtig? Irgendeine Idee was das sein könnte? – urSus

1

Ich empfehle einen Singleton Bitmap Cache, so dass dieser Cache während der gesamten Lebensdauer Ihrer App verfügbar ist.

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

Hier ist ein Beispiel einer Festplatte der Verwendung basierend LRU-Cache mit Volley. Es basiert auf einer Version von AOSPs DiskLruCache, die von Jake Wharton verwaltet wird. http://blogs.captechconsulting.com/blog/raymond-robinson/google-io-2013-volley-image-cache-tutorial

Bearbeiten: Ich habe das Projekt aktualisiert, um einen In-Memory-LRU-Cache als Standardimplementierung zu enthalten, da dies die empfohlene Methode ist. Volley behandelt implizit diskettenbasierten Cache in seinem eigenen L2-Cache. Der Image-Cache ist nur der L1-Cache. Ich habe den ursprünglichen Beitrag aktualisiert und einige weitere Details hinzugefügt: http://www.thekeyconsultant.com/2013/06/update-volley-image-cache.html.

+1

In Ihrer Bibliothek scheinen Sie url.hashCode() zu verwenden, um den vom Platten-Cache benötigten Schlüssel zu generieren. Ist das wirklich sicher? hashCodes sind nicht eindeutig, riskieren Sie also nicht, falsche Cache-Treffer für URLs zu erhalten, die nach dem Zufallsprinzip in denselben Hash-Code aufgelöst werden? Ich habe gesehen, wie andere MD5 verwenden, um das Risiko von Kollisionen zu reduzieren. Einige haben sogar ihre eigene MD5-Implementierung zur Verfügung gestellt, um Androids nicht-threadsichere MessageDigest-Klasse zu vermeiden. Irgendwelche Vorschläge bezüglich dieses (potenziellen) Problems? –

+1

Sie haben Recht, das wurde nur für die Demo erstellt und funktioniert die meiste Zeit. Ich prüfe die Geschwindigkeit von UUID.fromString() als eine brauchbare Alternative. – rdrobinson3

0

dies kommt in neue API die 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); 
    } 
}