Skip to content

Commit

Permalink
Issue #44 - Use Of Semaphore for avoiding unnecessary downloads/loads
Browse files Browse the repository at this point in the history
  • Loading branch information
nostra13 committed Sep 23, 2012
1 parent 4137c10 commit 87a4ee9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

import android.content.res.Configuration;
import android.graphics.Bitmap;
Expand Down Expand Up @@ -42,6 +43,7 @@ public class ImageLoader {
private ImageLoadingListener emptyListener;

private Map<ImageView, String> cacheKeyForImageView = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
private Map<String, ReentrantLock> uriLocks = Collections.synchronizedMap(new WeakHashMap<String, ReentrantLock>());

private volatile static ImageLoader instance;

Expand Down Expand Up @@ -209,7 +211,7 @@ public void displayImage(String uri, ImageView imageView, DisplayImageOptions op
}

checkExecutors();
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, options, listener);
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, options, listener, getLockForUri(uri));
LoadAndDisplayImageTask displayImageTask = new LoadAndDisplayImageTask(configuration, imageLoadingInfo, new Handler());
boolean isImageCachedOnDisc = configuration.discCache.get(uri).exists();
if (isImageCachedOnDisc) {
Expand Down Expand Up @@ -327,4 +329,15 @@ private int getFieldValue(Object object, String fieldName) {
}
return value;
}

private ReentrantLock getLockForUri(String uri) {
synchronized (uriLocks) {
ReentrantLock lock = uriLocks.get(uri);
if (lock == null) {
lock = new ReentrantLock();
uriLocks.put(uri, lock);
}
return lock;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.nostra13.universalimageloader.core;

import java.util.concurrent.locks.ReentrantLock;

import android.net.Uri;
import android.widget.ImageView;

Expand All @@ -23,13 +25,15 @@ final class ImageLoadingInfo {
final ImageSize targetSize;
final DisplayImageOptions options;
final ImageLoadingListener listener;
final ReentrantLock loadFromUriLock;

public ImageLoadingInfo(String uri, ImageView imageView, ImageSize targetSize, DisplayImageOptions options, ImageLoadingListener listener) {
public ImageLoadingInfo(String uri, ImageView imageView, ImageSize targetSize, DisplayImageOptions options, ImageLoadingListener listener, ReentrantLock loadFromUriLock) {
this.uri = Uri.encode(uri, "@#&=*+-_.,:!?()/~'%");
this.imageView = imageView;
this.targetSize = targetSize;
this.options = options;
this.listener = listener;
this.loadFromUriLock = loadFromUriLock;
memoryCacheKey = MemoryCacheKeyUtil.generateKey(uri, targetSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
final class LoadAndDisplayImageTask implements Runnable {

private static final String LOG_START_DISPLAY_IMAGE_TASK = "Start display image task [%s]";
private static final String LOG_WAITING = "Image already is loading. Waiting... [%s]";
private static final String LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING = "...Get cached bitmap from memory after waiting. [%s]";
private static final String LOG_LOAD_IMAGE_FROM_INTERNET = "Load image from Internet [%s]";
private static final String LOG_LOAD_IMAGE_FROM_DISC_CACHE = "Load image from disc cache [%s]";
private static final String LOG_CACHE_IMAGE_IN_MEMORY = "Cache image in memory [%s]";
Expand All @@ -52,17 +54,35 @@ public LoadAndDisplayImageTask(ImageLoaderConfiguration configuration, ImageLoad

@Override
public void run() {
if (configuration.loggingEnabled) Log.i(ImageLoader.TAG, String.format(LOG_START_DISPLAY_IMAGE_TASK, imageLoadingInfo.memoryCacheKey));
if (configuration.loggingEnabled) {
Log.i(ImageLoader.TAG, String.format(LOG_START_DISPLAY_IMAGE_TASK, imageLoadingInfo.memoryCacheKey));
if (imageLoadingInfo.loadFromUriLock.isLocked()) {
Log.i(ImageLoader.TAG, String.format(LOG_WAITING, imageLoadingInfo.memoryCacheKey));
}
}

if (checkTaskIsNotActual()) return;
Bitmap bmp = tryLoadBitmap();
if (bmp == null) return;
imageLoadingInfo.loadFromUriLock.lock();
Bitmap bmp;
try {
if (checkTaskIsNotActual()) return;

if (checkTaskIsNotActual()) return;
if (imageLoadingInfo.options.isCacheInMemory()) {
if (configuration.loggingEnabled) Log.i(ImageLoader.TAG, String.format(LOG_CACHE_IMAGE_IN_MEMORY, imageLoadingInfo.memoryCacheKey));
bmp = ImageLoader.getInstance().getMemoryCache().get(imageLoadingInfo.memoryCacheKey);
if (bmp == null) {
bmp = tryLoadBitmap();
if (bmp == null) return;

configuration.memoryCache.put(imageLoadingInfo.memoryCacheKey, bmp);
if (checkTaskIsNotActual()) return;
if (imageLoadingInfo.options.isCacheInMemory()) {
if (configuration.loggingEnabled) Log.i(ImageLoader.TAG, String.format(LOG_CACHE_IMAGE_IN_MEMORY, imageLoadingInfo.memoryCacheKey));

configuration.memoryCache.put(imageLoadingInfo.memoryCacheKey, bmp);
}
} else {
if (configuration.loggingEnabled)
Log.i(ImageLoader.TAG, String.format(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, imageLoadingInfo.memoryCacheKey));
}
} finally {
imageLoadingInfo.loadFromUriLock.unlock();
}

if (checkTaskIsNotActual()) return;
Expand Down

0 comments on commit 87a4ee9

Please sign in to comment.