package com.wigwamlabs.spotify.util; import android.graphics.Bitmap; import com.wigwamlabs.spotify.Debug; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class BitmapCacheHashMap<Key> extends LinkedHashMap<Key, Bitmap> { private static final int TINY_BITMAP_SIZE = 64 * 64 * 4; private final int mLimitBytes; private final int mLimitSize; private int mSizeBytes; public BitmapCacheHashMap(int limitSize, int limitBytes) { super(100, 0.75f, true); mLimitSize = limitSize; mLimitBytes = limitBytes; } @Override public void clear() { Debug.logBitmapCache("clearing"); mSizeBytes = 0; super.clear(); } @Override public Bitmap put(Key key, Bitmap value) { final Bitmap oldValue = super.put(key, value); if (oldValue != null) { final int size = oldValue.getRowBytes() * oldValue.getHeight(); Debug.logBitmapCache("replacing old bitmap: " + mSizeBytes + " - " + size + " = " + (mSizeBytes - size)); mSizeBytes -= size; } if (value != null) { final int size = value.getRowBytes() * value.getHeight(); Debug.logBitmapCache("adding new bitmap: " + mSizeBytes + " + " + size + " = " + (mSizeBytes + size)); mSizeBytes += size; removeOldEntries(); } return oldValue; } @Override public Bitmap remove(Object key) { final Bitmap oldValue = super.remove(key); if (oldValue != null) { final int bitmapSize = oldValue.getRowBytes() * oldValue.getHeight(); Debug.logBitmapCache("remove old bitmap: " + mSizeBytes + " - " + bitmapSize + " = " + (mSizeBytes - bitmapSize)); mSizeBytes -= bitmapSize; } return oldValue; } private void removeOldEntries() { // remove non-tiny bitmaps if (mSizeBytes > mLimitBytes) { final Iterator<Map.Entry<Key, Bitmap>> it = entrySet().iterator(); while (mSizeBytes > mLimitBytes) { if (!it.hasNext()) { break; } final Bitmap bitmap = it.next().getValue(); final int bitmapSize = (bitmap != null ? bitmap.getRowBytes() * bitmap.getHeight() : 0); if (bitmapSize > TINY_BITMAP_SIZE) { it.remove(); } } } // remove entries no matter which size int entriesToRemove = size() - mLimitSize; if (entriesToRemove > 0) { final Iterator<Map.Entry<Key, Bitmap>> it = entrySet().iterator(); while (entriesToRemove > 0) { if (!it.hasNext()) { break; } it.next(); it.remove(); entriesToRemove--; } } } }