LinkedHashMap과 SoftReference사용 Cache처리를 하는 로직이다.
한번 디스크에서 읽은 bitmap을 키값에 대응하여 저장한다.
인터넷의 아래 소스를 퍼왔다.
http://code.google.com/p/android-imagedownloader/source/browse/trunk/src/com/example/android/imagedownloader/ImageDownloader.java
구조는 LinkedHashMap을 사용한 HARD CASH와 SoftReference를 사용하여 메모리가 부족할때
GC의 대상이 될수 있도록 한 HashMap 2가지가 유기적으로 동작한다.
private static final int HARD_CACHE_CAPACITY = 10;
private final HashMap<Long, Bitmap> sHardBitmapCache = new LinkedHashMap<Long, Bitmap>(
HARD_CACHE_CAPACITY / 2, 0.75f, true) {
@Override
protected boolean removeEldestEntry(
LinkedHashMap.Entry<Long, Bitmap> eldest) {
if (size() > HARD_CACHE_CAPACITY) {
// Entries push-out of hard reference cache are transferred to
// soft reference cache
sSoftBitmapCache.put(eldest.getKey(),
new SoftReference<Bitmap>(eldest.getValue()));
return true;
} else
return false;
}
};
// Soft cache for bitmaps kicked out of hard cache
private final static ConcurrentHashMap<Long, SoftReference<Bitmap>> sSoftBitmapCache = new ConcurrentHashMap<Long, SoftReference<Bitmap>>(
HARD_CACHE_CAPACITY / 2);
removeEldestEntry 함수는 LinkedHashMap 에 put할 경우 자동 호출되는 명령어로
true를 호출하게 되면 내부적으로 가장 먼저 들어왔던 항목을 버리도록 되어있다.
removeEldestEntry 함수를 Override하여 HARD_CACHE_CAPACITY 보다 사이즈가
커졌을 경우 sSoftBitmapCache에 넣도록 구현했다. 이후 true를 return했으므로 sHardBitmapCache 에
가장 먼저 들어왔던 항목은 삭제된다.
public void addBitmapToCache(Long id, Bitmap bitmap) {
LOG.i(CLASSNAME, "addBitmapToCache id : "+id+" , bitmap : "+bitmap);
LOG.i(CLASSNAME, "addBitmapToCache sHardBitmapCache.size() : "+sHardBitmapCache.size()+" , sSoftBitmapCache.size() : "+sSoftBitmapCache.size());
if (bitmap != null) {
synchronized (sHardBitmapCache) {
sHardBitmapCache.put(id, bitmap);
}
}
}
sHardBitmapCache 에 데이터를 넣는다.
public Bitmap getBitmapFromCache(long id) {
LOG.i(CLASSNAME, "getBitmapFromCache id : "+id);
LOG.i(CLASSNAME, "getBitmapFromCache sHardBitmapCache.size() : "+sHardBitmapCache.size()+" , sSoftBitmapCache.size() : "+sSoftBitmapCache.size());
synchronized (sHardBitmapCache) {
final Bitmap bitmap = sHardBitmapCache.get(id);
if (bitmap != null) {
// Bitmap found in hard cache
// Move element to first position, so that it is removed last
sHardBitmapCache.remove(id);
sHardBitmapCache.put(id, bitmap);
return bitmap;
}
}
// Then try the soft reference cache
SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(id);
if (bitmapReference != null) {
final Bitmap bitmap = bitmapReference.get();
if (bitmap != null) {
// Bitmap found in soft cache
return bitmap;
} else {
// Soft reference has been Garbage Collected
sSoftBitmapCache.remove(id);
}
}
return null;
}
구현된 getBitmapFromCache 함수를 사용하여 Cache에 해당 키값에 대한 데이터가 있으면 가져온다.
sHardBitmapCache remove하고 다시 put하는 동작으로 최근에 사용된 데이터가 항상 최신을 유지하도록 한다. 앞서 Override한 removeEldestEntry 함수 덕분에 사용하지 않는 데이터는 쓰다보면 삭제되게 되어있다.
sHardBitmapCache에 찾고자 하는 데이터가 없다면 sSoftBitmapCache 를 검색한다.
** Thumbnail을 가져오기 위해 기 구현된 AsyncTask를 상속받아 구현한 객체를 생성하기 전에
위 자료 구조를 사용하여 Map에 저장된 bitmap을 가져오면 반응 속도를 향상 시킬수 있다.
그러나 Memory Leak에 대해서는 관심이 필요할 것으로 보인다.
'PROGRAMING > Android' 카테고리의 다른 글
Fragment에서 하단 OptionMenu 사용하는 방법 (0) | 2013.02.24 |
---|---|
listView에서 checkbox 넣을 경우. 뷰 재사용 때문에 발생되는 문제 수정. (0) | 2013.02.24 |
listView 항목에 Audio Albumart(thumbnail)을 지연 없이 나타내기 AsyncTask 호출 늦게 하기 (0) | 2013.02.23 |
listView 항목에 Audio Albumart(thumbnail)을 지연 없이 나타내기.AsyncTask (1) | 2013.02.22 |
Audio AlbumArt 가져오기. (0) | 2013.02.22 |