Skip to content

Instantly share code, notes, and snippets.

@tombowers
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tombowers/085afd46bbd55fd67758 to your computer and use it in GitHub Desktop.
Save tombowers/085afd46bbd55fd67758 to your computer and use it in GitHub Desktop.
Xamarin Android – Using Remote Images in Lists
/// <summary>
/// An AsyncTask that will asynchronously download an image and assign it to an ImageView.
/// </summary>
public class BitmapDownloaderTask : AsyncTask<String, Java.Lang.Void, Bitmap>
{
private readonly ImageView _imageView;
public BitmapDownloaderTask(ImageView imageView)
{
if (imageView == null)
throw new ArgumentNullException("imageView");
_imageView = imageView;
}
public string Url { get; private set; }
/// <summary>
/// Called on a background thread when the task is executed.
/// </summary>
protected override Bitmap RunInBackground(params string[] @params)
{
Url = @params[0];
return DownloadRemoteImage(Url);
}
/// <summary>
/// Once the image is downloaded, associates it to the imageView
/// </summary>
protected override void OnPostExecute(Bitmap bitmap)
{
if (IsCancelled)
bitmap = null;
imageView.SetImageBitmap(bitmap);
}
private Bitmap DownloadRemoteImage(string url)
{
if (string.IsNullOrWhiteSpace(url))
throw new ArgumentException("url must not be null, empty, or whitespace");
Uri imageUri;
if (!Uri.TryCreate(url, UriKind.Absolute, out imageUri))
throw new ArgumentException("Invalid url");
try
{
WebRequest request = HttpWebRequest.Create(imageUri);
request.Timeout = 10000;
WebResponse response = request.GetResponse();
Stream inputStream = response.GetResponseStream();
return BitmapFactory.DecodeStream(inputStream);
}
catch (Exception)
{
return null;
}
}
}
/// <summary>
/// An AsyncTask that will asynchronously download an image and assign it to an ImageView.
/// </summary>
public class BitmapDownloaderTask : AsyncTask<String, Java.Lang.Void, Bitmap>
{
private readonly WeakReference<ImageView> _imageViewReference;
public BitmapDownloaderTask(ImageView imageView)
{
if (imageView == null)
throw new ArgumentNullException("imageView");
_imageViewReference = new WeakReference<ImageView>(imageView);
}
...
/// <summary>
/// Once the image is downloaded, associates it to the imageView
/// </summary>
protected override void OnPostExecute(Bitmap bitmap)
{
if (IsCancelled)
bitmap = null;
if (_imageViewReference != null && bitmap != null)
{
ImageView imageView;
if (!_imageViewReference.TryGetTarget(out imageView))
return;
var bitmapDownloaderTask = imageView.GetBitmapDownloaderTask();
// Change bitmap only if this process is still associated with it.
// This is necessary as views can be reused by Android, and a newer BitmapDownloader instance may have been attached to it.
if (this == bitmapDownloaderTask)
imageView.SetImageBitmap(bitmap);
}
}
...
}
var task = new BitmapDownloaderTask(imageView);
imageView.SetImageDrawable(new DownloadedDrawable(task, Color.Gray));
imageView.SetMinimumHeight(300);
task.Execute("http://placehold.it/300x300");
var task = new BitmapDownloaderTask(imageView);
imageView.SetImageDrawable(new ColorDrawable(Color.Gray));
imageView.SetMinimumHeight(300);
task.Execute("http://placehold.it/300x300");
/// <summary>
/// Retrieve the BitmapDownloaderTask from the ImageView's drawable.
/// This will return null if the drawable is not a DownloadedDrawable, or there is no BitmapDownloaderTask attached to it.
/// </summary>
public static BitmapDownloaderTask GetBitmapDownloaderTask(this ImageView imageView)
{
if (imageView != null)
{
var drawable = imageView.Drawable as DownloadedDrawable;
if (drawable != null)
return drawable.GetBitmapDownloaderTask();
}
return null;
}
/// <summary>
/// A fake Drawable that will be attached to the ImageView while the download is in progress.
/// Contains a reference to the actual download task, so that a download task can be stopped
/// if a new binding is required, and makes sure that only the last started download process can
/// bind its result, independently of the download finish order.
/// </summary>
public class DownloadedDrawable : ColorDrawable
{
private readonly WeakReference<BitmapDownloaderTask> _bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask, Color loadingBackgroundColor)
: base(loadingBackgroundColor)
{
_bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
public BitmapDownloaderTask GetBitmapDownloaderTask()
{
BitmapDownloaderTask task;
_bitmapDownloaderTaskReference.TryGetTarget(out task);
return task;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment