2013-05-22 12 views

Odpowiedz

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

dzięki dużo, przy okazji, jak można określić właściwą wielkość pamięci podręcznej? mówi o tym, że jest to funkcja wielkości ekranu, wydaje się logiczne, ale w jaki sposób mogę ją dokładniej określić? – urSus

+0

@Vlasto Benny Lava, nie jestem pewien, ale coś takiego jak 'N * screen_width * screen_height' z' N ~ 10' wydaje mi się logiczne. –

+0

ponieważ teraz to, co się dzieje, działa dobrze, ale obraz ładuje się ponownie, jeśli zniknie z ekranu i wróci, więc zakładam, że został wyrzucony z pamięci podręcznej, prawda? Masz pojęcie, co to może być? – urSus

1

Radzę użyć pamięci podręcznej bitmap Singleton, aby ta pamięć podręczna była dostępna przez cały okres użytkowania aplikacji.

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

Oto przykład z użyciem dysku w oparciu LRU cache z Volley. Opiera się on na używaniu wersji DiskLruCache AOSP utrzymywanej przez Jake'a Whartona. http://blogs.captechconsulting.com/blog/raymond-robinson/google-io-2013-volley-image-cache-tutorial

Edycja: Zaktualizowałem projekt tak, aby uwzględniał pamięć podręczną LRU w pamięci jako domyślną implementację, ponieważ jest to zalecana metoda. Volley niejawnie obsługuje pamięć podręczną opartą na dyskach w swojej własnej pamięci podręcznej L2. Pamięć podręczna obrazu to pamięć podręczna L1. Zaktualizowałem oryginalny post i dodałem trochę więcej szczegółów tutaj: http://www.thekeyconsultant.com/2013/06/update-volley-image-cache.html.

+1

W bibliotece wydaje się, że używasz url.hashCode() do generowania klucza wymaganego przez pamięć podręczną dysku. Czy to naprawdę bezpieczne? hashCodes nie są unikatowe, więc czy nie ryzykujesz fałszywymi trafieniami w pamięci podręcznej adresów URL, które losowo rozwiązują ten sam kod skrótu? Widziałem, jak inni używają MD5, aby zmniejszyć ryzyko kolizji, niektórzy nawet wprowadzają własną implementację MD5, aby uniknąć Androidów bez wątków klasy MessageDigest. Wszelkie sugestie dotyczące tego (potencjalnego) problemu? –

+1

Masz rację, to zostało po prostu wprowadzone na demo i działa przez większość czasu. Testuję szybkość UUID.fromString() jako realną alternatywę. – rdrobinson3

0

ten jest wyposażony w nowy interfejs API do obsługi 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); 
    } 
} 
Powiązane problemy