Created
December 8, 2011 20:42
-
-
Save joelmartinez/1448479 to your computer and use it in GitHub Desktop.
Android ImageDownloader (from random StackOverflow thread)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.your.project; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.lang.ref.SoftReference; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.net.URLConnection; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.Map; | |
import java.util.WeakHashMap; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import android.content.Context; | |
import android.graphics.drawable.Drawable; | |
import android.os.Handler; | |
import android.os.Message; | |
import android.util.Log; | |
import android.widget.ImageView; | |
public class ImageDownloader { | |
private static final String TAG = "ImageDownloader"; | |
private final Map<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>(); | |
private final LinkedList<Drawable> mChacheController = new LinkedList<Drawable>(); | |
private ExecutorService mThreadPool; | |
private final Map<ImageView, String> mImageViews = Collections | |
.synchronizedMap(new WeakHashMap<ImageView, String>()); | |
public static int MAX_CACHE_SIZE = 80; | |
public int THREAD_POOL_SIZE = 3; | |
private Context context; | |
public ImageDownloader(Context c) { | |
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); | |
this.context = c; | |
} | |
/** | |
* Clears all instance data and stops running threads | |
*/ | |
public void reset() { | |
ExecutorService oldThreadPool = mThreadPool; | |
mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); | |
oldThreadPool.shutdownNow(); | |
mChacheController.clear(); | |
mCache.clear(); | |
mImageViews.clear(); | |
} | |
public void loadDrawable(final String url, final ImageView imageView) { | |
Drawable d = this.context.getResources().getDrawable(R.drawable.sm_unknownuser); | |
this.loadDrawable(url, imageView, d); | |
} | |
public void loadDrawable(final String url, final ImageView imageView, | |
Drawable placeholder) { | |
mImageViews.put(imageView, url); | |
Drawable drawable = getDrawableFromCache(url); | |
// check in UI thread, so no concurrency issues | |
if (drawable != null) { | |
Log.d(TAG, "Item loaded from mCache: " + url); | |
imageView.setImageDrawable(drawable); | |
} else { | |
Log.d(TAG, "Item not found in cache: " + url); | |
imageView.setImageDrawable(placeholder); | |
queueJob(url, imageView, placeholder); | |
} | |
} | |
private Drawable getDrawableFromCache(String url) { | |
if (mCache.containsKey(url)) { | |
return mCache.get(url).get(); | |
} | |
return null; | |
} | |
private synchronized void putDrawableInCache(String url, Drawable drawable) { | |
int chacheControllerSize = mChacheController.size(); | |
if (chacheControllerSize > MAX_CACHE_SIZE) | |
mChacheController.subList(0, MAX_CACHE_SIZE / 2).clear(); | |
mChacheController.addLast(drawable); | |
mCache.put(url, new SoftReference<Drawable>(drawable)); | |
Log.d(TAG, "Item added to mCache: " + url); | |
} | |
private void queueJob(final String url, final ImageView imageView, | |
final Drawable placeholder) { | |
/* Create handler in UI thread. */ | |
final Handler handler = new Handler() { | |
@Override | |
public void handleMessage(Message msg) { | |
String tag = mImageViews.get(imageView); | |
if (tag != null && tag.equals(url)) { | |
if (imageView.isShown()) | |
if (msg.obj != null) { | |
imageView.setImageDrawable((Drawable) msg.obj); | |
} else { | |
imageView.setImageDrawable(placeholder); | |
// Log.d(null, "fail " + url); | |
} | |
} | |
} | |
}; | |
mThreadPool.submit(new Runnable() { | |
@Override | |
public void run() { | |
final Drawable bmp = downloadDrawable(url); | |
// if the view is not visible anymore, the image will be ready | |
// for next time in cache | |
if (imageView.isShown()) { | |
Message message = Message.obtain(); | |
message.obj = bmp; | |
// Log.d(null, "Item downloaded: " + url); | |
handler.sendMessage(message); | |
} | |
} | |
}); | |
} | |
private Drawable downloadDrawable(String url) { | |
try { | |
Log.d("downloader", "downloading image: " + url); | |
InputStream is = getInputStream(url); | |
Drawable drawable = Drawable.createFromStream(is, url); | |
putDrawableInCache(url, drawable); | |
return drawable; | |
} catch (MalformedURLException e) { | |
e.printStackTrace(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
private InputStream getInputStream(String urlString) | |
throws MalformedURLException, IOException { | |
URL url = new URL(urlString); | |
URLConnection connection; | |
connection = url.openConnection(); | |
connection.setUseCaches(true); // | |
Object response = connection.getContent(); | |
if (!(response instanceof InputStream)) | |
throw new IOException( | |
"URLConnection response is not instanceof InputStream"); | |
return (InputStream) response; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment