package com.androidol.util.tiles;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import com.androidol.constants.UtilConstants;
import com.androidol.tile.Tile;
import com.androidol.util.Util;
//import com.androidol.util.Util;
import android.graphics.Bitmap;
import android.util.Log;
public class LRUTileArrayCache implements UtilConstants {
private static final long serialVersionUID = 1L;
private final int maxCacheSize; // Maximum cache size
private final LinkedList<String> list; // Least Recently Used (LRU) list/
private Bitmap[] bitmapArray;
private HashMap<String, Integer> bitmapPositionArray;
private int cursor;
/**
* Constructor LRUTileArrayCache
*
* @param maxCacheSize
*/
public LRUTileArrayCache(final int maxCacheSize) {
this.maxCacheSize = Math.max(0, maxCacheSize);
this.list = new LinkedList<String>();
this.bitmapArray = new Bitmap[this.maxCacheSize];
this.bitmapPositionArray = new HashMap<String, Integer>(maxCacheSize);
this.cursor = 0;
}
/**
* API Method: clear
*/
public synchronized void clear() {
this.list.clear();
this.bitmapPositionArray.clear();
// recycle Bitmaps in array
for(int i=0; i<this.bitmapArray.length; i++) {
if(this.bitmapArray[i]!=null && this.bitmapArray[i].isRecycled()==false) {
this.bitmapArray[i].recycle();
this.bitmapArray[i] = null;
}
}
}
/**
* API Method: put
*
* @param key
* @param value
*/
public synchronized Bitmap put(final String url, final Bitmap value) {
if(maxCacheSize == 0) {
return null;
}
if(!this.bitmapPositionArray.containsKey(url) && !list.isEmpty() && list.size()+1 > maxCacheSize) {
final Object deadKey = list.removeLast();
// TODO: recycle the bitmap to avoid memory leak
Integer deadIntKey = this.bitmapPositionArray.remove(deadKey);
if(this.bitmapArray[deadIntKey.intValue()]!=null) {
this.bitmapArray[deadIntKey.intValue()].recycle();
this.bitmapArray[deadIntKey.intValue()] = null;
this.cursor = deadIntKey;
}
//Util.printDebugMessage(" ...bitmap get recycled...");
}
updateKey(url);
//printCurrentMemoryCacheStatus();
while(this.bitmapArray[this.cursor] != null) {
this.cursor = (this.cursor + 1) % this.maxCacheSize;
}
this.bitmapPositionArray.put(url, new Integer(this.cursor));
this.bitmapArray[this.cursor] = value;
return this.bitmapArray[this.cursor];
}
/**
* API Method: put
*
* @param key
* @param value
*/
public synchronized Bitmap put(final String url, final Bitmap value, final Tile tile) {
return put(url, value);
}
/**
* API Method: get
*
* @param key
* @return bitmap
*
*/
public synchronized Bitmap get(final String url) {
if(this.bitmapPositionArray.get(url) == null) {
return null;
};
final Bitmap value = this.bitmapArray[this.bitmapPositionArray.get(url).intValue()];
if(value != null) {
updateKey(url);
}
return value;
}
/**
*
* @param key
* @return
*/
public synchronized Bitmap remove(final String url) {
list.remove(url);
//printCurrentMemoryCacheStatus();
if(this.bitmapPositionArray.get(url)==null) {return null;};
return this.bitmapArray[this.bitmapPositionArray.remove(url)];
}
/**
* API Method: updateKey
* update the key to be the first in the list
*
* @param key
*/
private void updateKey(final String url) {
this.list.remove(url);
this.list.addFirst(url);
}
/**
* API Method: printCurrentMemoryCacheStatus
*/
/*
public void printCurrentMemoryCacheStatus() {
Log.i(DEBUGTAG, " //=============================================================================");
Log.i(DEBUGTAG, " //...total memory cache size (in tiles): " + maxCacheSize);
Log.i(DEBUGTAG, " //...used memory cache size (in tiles): " + this.list.size());
Log.i(DEBUGTAG, " //=============================================================================");
}
*/
}