Created
March 24, 2011 03:02
-
-
Save koush/884471 to your computer and use it in GitHub Desktop.
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
/* | |
* UrlImageCache.java | |
* | |
* Copyright 2010, BuddyTV. All Rights Reserved | |
* Created 12/13/2010 Mike Markley | |
*/ | |
package com.buddytv.android.utilities; | |
import android.graphics.drawable.Drawable; | |
public final class UrlImageCache extends WeakReferenceHashTable<String, Drawable> { | |
private static UrlImageCache mInstance = new UrlImageCache(); | |
public static UrlImageCache getInstance() { | |
return mInstance; | |
} | |
private UrlImageCache() { | |
} | |
} |
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.buddytv.android.utilities; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.net.URL; | |
import java.net.URLConnection; | |
import java.util.ArrayList; | |
import java.util.Hashtable; | |
import com.buddytv.android.Helper; | |
import android.content.Context; | |
import android.content.res.Configuration; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.graphics.BitmapFactory.Options; | |
import android.graphics.drawable.BitmapDrawable; | |
import android.graphics.drawable.Drawable; | |
import android.os.AsyncTask; | |
import android.util.Log; | |
import android.widget.ImageView; | |
public final class UrlImageViewHelper { | |
private static final String LOGTAG = "UrlImageViewHelper"; | |
public static int copyStream(InputStream input, OutputStream output) throws IOException | |
{ | |
byte[] stuff = new byte[1024]; | |
int read = 0; | |
int total = 0; | |
while ((read = input.read(stuff)) != -1) | |
{ | |
output.write(stuff, 0, read); | |
total += read; | |
} | |
return total; | |
} | |
public static void setUrlDrawable(final ImageView imageView, final String url, int defaultResource) { | |
if (Helper.isNullOrEmpty(url)) { | |
imageView.setImageDrawable(null); | |
return; | |
} | |
final UrlImageCache cache = UrlImageCache.getInstance(); | |
Drawable d = cache.get(url); | |
if (d != null) { | |
//Log.i(LOGTAG, "Cache hit on: " + url); | |
final Drawable newImage = d; | |
imageView.post(new Runnable() { | |
public void run() { | |
imageView.setImageDrawable(newImage); | |
} | |
}); | |
return; | |
} | |
final String filename = "" + url.hashCode() + ".png"; | |
if (imageView.getContext().getFileStreamPath(filename).exists()) { | |
try { | |
FileInputStream fis = imageView.getContext().openFileInput(filename); | |
final Bitmap bitmap = BitmapFactory.decodeStream(fis); | |
BitmapDrawable drawable = new BitmapDrawable(bitmap); | |
imageView.setImageDrawable(drawable); | |
cache.put(url, drawable); | |
Log.i(LOGTAG, "File Cache hit on: " + url); | |
return; | |
} | |
catch (Exception ex) { | |
} | |
} | |
// null it while it is downloading | |
if (defaultResource == 0) | |
imageView.setImageDrawable(null); | |
else | |
imageView.setImageResource(defaultResource); | |
// since listviews reuse their views, we need to | |
// take note of which url this view is waiting for. | |
// This may change rapidly as the list scrolls or is filtered, etc. | |
//Log.i(LOGTAG, "Waiting for " + url); | |
mPendingViews.put(imageView, url); | |
ArrayList<ImageView> currentDownload = mPendingDownloads.get(url); | |
if (currentDownload != null) { | |
// Also, multiple vies may be waiting for this url. | |
// So, let's maintain a list of these views. | |
// When the url is downloaded, it sets the imagedrawable for | |
// every view in the list. It needs to also validate that | |
// the imageview is still waiting for this url. | |
currentDownload.add(imageView); | |
return; | |
} | |
final ArrayList<ImageView> downloads = new ArrayList<ImageView>(); | |
downloads.add(imageView); | |
mPendingDownloads.put(url, downloads); | |
AsyncTask<Void, Void, Drawable> downloader = new AsyncTask<Void, Void, Drawable>() { | |
@Override | |
protected Drawable doInBackground(Void... params) { | |
try { | |
//Log.i(LOGTAG, "Downloading image: " + url); | |
URLConnection conn = new URL(url).openConnection(); | |
int len = conn.getContentLength(); | |
if (len < 0) | |
len = 0; | |
final InputStream is = conn.getInputStream(); | |
final Configuration configuration = new Configuration(); | |
configuration.setToDefaults(); | |
Options opts = new Options(); | |
// set the SampleSize to a value larger than 1 to get the image to | |
// be scaled. This also saves space on decoding in BitmapFactory | |
opts.inSampleSize = 2; | |
FileOutputStream fos = imageView.getContext().openFileOutput(filename, Context.MODE_PRIVATE); | |
copyStream(is, fos); | |
FileInputStream fis = imageView.getContext().openFileInput(filename); | |
final Bitmap bitmap = BitmapFactory.decodeStream(fis); | |
//Log.i(LOGTAG, String.format("Downloaded bitmap (%dx%d): %s", bitmap.getWidth(), bitmap.getHeight(), url)); | |
return new BitmapDrawable(bitmap); | |
//final Resources resources = new Resources(manager, metrics, configuration); | |
//BitmapDrawable b = new BitmapDrawable(resources, bitmap); | |
// Drawable d = Drawable.createFromStream(is, "src name"); | |
//return (Drawable) b; | |
} | |
catch (Exception ex) { | |
Log.e(LOGTAG, "Exception during Image download of " + url, ex); | |
return null; | |
} | |
} | |
protected void onPostExecute(Drawable result) { | |
mPendingDownloads.remove(url); | |
cache.put(url, result); | |
for (ImageView iv: downloads) { | |
// validate the url it is waiting for | |
String pendingUrl = mPendingViews.get(iv); | |
if (!url.equals(pendingUrl)) { | |
//Log.i(LOGTAG, "Ignoring out of date request ot update view for " + url); | |
continue; | |
} | |
mPendingViews.remove(iv); | |
if (result != null) { | |
final Drawable newImage = result; | |
final ImageView imageView = iv; | |
imageView.post(new Runnable() { | |
public void run() { | |
imageView.setImageDrawable(newImage); | |
} | |
}); | |
} | |
} | |
} | |
}; | |
downloader.execute(); | |
} | |
private static Hashtable<ImageView, String> mPendingViews = new Hashtable<ImageView, String>(); | |
private static Hashtable<String, ArrayList<ImageView>> mPendingDownloads = new Hashtable<String, ArrayList<ImageView>>(); | |
} |
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.buddytv.android.utilities; | |
import java.lang.ref.WeakReference; | |
import java.util.Hashtable; | |
public class WeakReferenceHashTable<K,V> { | |
Hashtable<K, WeakReference<V>> mTable = new Hashtable<K, WeakReference<V>>(); | |
public V put(K key, V value) { | |
WeakReference<V> old = mTable.put(key, new WeakReference<V>(value)); | |
if (old == null) | |
return null; | |
return old.get(); | |
} | |
public V get(K key) { | |
WeakReference<V> val = mTable.get(key); | |
if (val == null) | |
return null; | |
V ret = val.get(); | |
if (ret == null) | |
mTable.remove(key); | |
return ret; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment