Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
This is a simple version of UrlBitmapDrawable, an Android Drawable that can automatically reload a URL from an image library.
/**
* This is a version of BitmapDrawable that's associated with a particular URL.
* It automatically caches and reloads itself as its Bitmap is flushed from memory.
*
* When using this with an ImageView, use loadImageView(), as there is some special
* handling needed when using ImageViews.
*/
public class UrlBitmapDrawable extends BitmapDrawable {
private String mUrl;
private Bitmap mDefaultBitmap;
private WeakReference<ImageView> mImageView;
private boolean mRetrieving;
private boolean mFailed;
public UrlBitmapDrawable(Resources resources, String url, Bitmap defaultBitmap) {
super(resources, defaultBitmap);
mUrl = url;
mDefaultBitmap = defaultBitmap;
// Start loading immediately
retrieveImage(false);
}
/*
* We need to do perform a hack to work properly with ImageViews,
* so most of the time you will be using this method.
*/
public static UrlBitmapDrawable loadImageView(String url, ImageView imageView, Bitmap defaultBitmap) {
UrlBitmapDrawable drawable = new UrlBitmapDrawable(imageView.getContext().getResources(), url, defaultBitmap);
// If there's already a UrlBitmapDrawable associated with this ImageView,
// disassociate it (so we don't have two UrlBitmapDrawables trying to
// operate on the same ImageView).
Drawable currDrawable = imageView.getDrawable();
if (currDrawable instanceof UrlBitmapDrawable) {
((UrlBitmapDrawable) currDrawable).mImageView = null;
}
imageView.setImageDrawable(drawable);
drawable.mImageView = new WeakReference<ImageView>(imageView);
return drawable;
}
@Override
public void draw(Canvas canvas) {
// If URL not set, or we could not retrieve the image for this drawable, don't draw (or draw default)
if (mFailed) {
if (mDefaultBitmap != null) {
super.draw(canvas);
}
return;
}
// If URL not loaded (either being null or recycled), load it now (and fallback to default)
Bitmap bitmap = getBitmap();
if (bitmap == null || bitmap.isRecycled()) {
if (mDefaultBitmap != null) {
setBitmap(mDefaultBitmap);
}
retrieveImage(false);
}
else {
super.draw(canvas);
}
}
private void retrieveImage(boolean forceRetrieve) {
if (!mRetrieving || forceRetrieve) {
mRetrieving = true;
MyImageLib.loadImage(mUrl, mCallbacks);
}
}
private MyImageCallbacks mCallbacks = new MyImageCallbacks() {
@Override
public void onLoad(Bitmap bitmap) {
if (bitmap != null) {
setBitmap(bitmap);
// This is a hack to get the ImageView to re-measure the
// width/height of this Drawable without having to completely
// re-implement ImageView. Without a re-measure this drawable
// can end up skewed in the ImageView.
if (mImageView != null) {
final ImageView imageView = mImageView.get();
if (imageView != null) {
imageView.setImageDrawable(null);
imageView.setImageDrawable(UrlBitmapDrawable.this);
}
}
}
else {
mFailed = true;
}
mRetrieving = false;
}
};
//////////////////////////////////////////////////////////////////////////
// These are stand-ins for an actual image loading library
public static interface MyImageCallbacks {
public void onLoad(Bitmap bitmap);
}
private static class MyImageLib {
private static void loadImage(String url, MyImageCallbacks callbacks) {
// Implement an image loading library here
}
}
}
@hzsweers

Just a heads up, it looks like setBitmap is now private in BitmapDrawable. Any idea how to get around that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment