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에 대해서는 관심이 필요할 것으로 보인다.
'프로그래밍 > 안드로이드' 카테고리의 다른 글
안드로이드 - GCM 활용해서 푸시 메세지 전송기 (0) | 2013.12.22 |
---|---|
안드로이드 - XmlPullParser 사용시 유의법(규칙) (0) | 2013.12.18 |
안드로이드 - ImageDownloader 분석 (0) | 2013.12.07 |
안드로이드/Android AsyncTask 사용법 (0) | 2013.12.07 |
안드로이드 - HashMap,HashTable,LinkedHashMap,ConcurrentHashMap (0) | 2013.12.05 |
안드로이드 - Android Handler 와 Timer(TimerTask) 를 활용한 Intro 화면 구성 (0) | 2013.12.05 |
안드로이드 - Bitmap OutOfMemoryError 해결책 (0) | 2013.12.05 |
안드로이드 XmlPullParser 사용 예제 (0) | 2013.12.01 |