package org.mozilla.osmdroid.tileprovider;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import java.util.LinkedList;
/*
* @TODO: vng
* This is crazy. We don't know how much heap or native memory is on
* the device, so we don't know how many Bitmap instances we can
* reliably hold on to.
*
* mPool is an unbounded LinkedList and everytime the LRUMapTileCache
* evicts a tile, it goes back into the pool.
*/
public class BitmapPool {
private static BitmapPool sInstance;
final LinkedList<Bitmap> mPool = new LinkedList<Bitmap>();
public static BitmapPool getInstance() {
if (sInstance == null) {
sInstance = new BitmapPool();
}
return sInstance;
}
public void returnDrawableToPool(ReusableBitmapDrawable drawable) {
Bitmap b = drawable.tryRecycle();
if (b != null && b.isMutable()) {
synchronized (mPool) {
mPool.addLast(b);
}
}
}
public void applyReusableOptions(final BitmapFactory.Options aBitmapOptions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
aBitmapOptions.inBitmap = obtainBitmapFromPool();
aBitmapOptions.inSampleSize = 1;
aBitmapOptions.inMutable = true;
}
}
public Bitmap obtainBitmapFromPool() {
synchronized (mPool) {
if (mPool.isEmpty()) {
return null;
} else {
final Bitmap bitmap = mPool.removeFirst();
if (bitmap.isRecycled()) {
return obtainBitmapFromPool(); // recurse
} else {
return bitmap;
}
}
}
}
public Bitmap obtainSizedBitmapFromPool(final int aWidth, final int aHeight) {
synchronized (mPool) {
if (mPool.isEmpty()) {
return null;
} else {
for (final Bitmap bitmap : mPool) {
if (bitmap.isRecycled()) {
mPool.remove(bitmap);
return obtainSizedBitmapFromPool(aWidth, aHeight); // recurse to prevent ConcurrentModificationException
} else if (bitmap.getWidth() == aWidth && bitmap.getHeight() == aHeight) {
mPool.remove(bitmap);
return bitmap;
}
}
}
}
return null;
}
public void clearBitmapPool() {
synchronized (sInstance.mPool) {
while (!sInstance.mPool.isEmpty()) {
Bitmap bitmap = sInstance.mPool.remove();
bitmap.recycle();
}
}
}
}