This code addresses performance issues specific to Android running Xamarin / C# when downloading images (BMP/PNG) into a listview. The caller simply specifies the URL to fetch the image from, and the preferred dimensions.Optimisations I could do, but haven't:Not sure if I should use the Android or Java namespaceStage the downloaded byte[] in an intermediate location - not sure if memory exhaustion is possibleImage cachingConvert to an Android DrawableAbstract the source to be something other than a URL, e.g. the local resourcesMake a static helper class (not sure how to do this...)using System;using System.Threading.Tasks;using Android.Graphics;using Android.Content.Res;using System.Net;namespace validAndroid{    public class ImageUtils    {        async Task<BitmapFactory.Options> GetBitmapOptionsOfImageAsync(byte[] imageBytes)        {            BitmapFactory.Options options = new BitmapFactory.Options {                /*Setting the InJustDecodeBounds property to true while decoding avoids memory allocation,                 * returning null for the bitmap object but setting OutWidth, OutHeight and OutMimeType .                 * This technique allows you to read the dimensions and type of the image data prior to                 * construction (and memory allocation) of the bitmap.*/                InJustDecodeBounds = true            };            // The result will be null because InJustDecodeBounds == true.            Bitmap result = await BitmapFactory.DecodeByteArrayAsync (imageBytes, 0, imageBytes.Length -1, options);            int imageHeight = options.OutHeight;            int imageWidth = options.OutWidth;            System.Diagnostics.Debug.WriteLine (string.Format (Original Size= {0}x{1}, imageWidth, imageHeight));            return options;        }          static int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)        {            // Raw height and width of image            float height = options.OutHeight;            float width = options.OutWidth;            double inSampleSize = 1D;            if (height > reqHeight || width > reqWidth)            {                int halfHeight = (int)(height / 2);                int halfWidth = (int)(width / 2);                // Calculate a inSampleSize that is a power of 2 - the decoder will use a value that is a power of two anyway.                while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)                {                    inSampleSize *= 2;                }            }            return (int)inSampleSize;        }        async Task<Android.Graphics.Bitmap> LoadScaledDownBitmapForDisplayAsync(byte[] imageBytes, BitmapFactory.Options options, int reqWidth, int reqHeight)        {            // Calculate inSampleSize            options.InSampleSize = CalculateInSampleSize (options, reqWidth, reqHeight);            // Decode bitmap with inSampleSize set            options.InJustDecodeBounds = false;            return await Android.Graphics.BitmapFactory.DecodeByteArrayAsync (imageBytes,0,imageBytes.Length-1,  options);        }        public  async  Task<Bitmap> GetImageForDisplay(string imageURL,int reqWidth, int reqHeight )        {            byte[] imageBytes = null;            using (var webClient = new WebClient())            {                imageBytes= webClient.DownloadData(imageURL);            }            BitmapFactory.Options options = await GetBitmapOptionsOfImageAsync(imageBytes);            var bitmapToDisplay = await LoadScaledDownBitmapForDisplayAsync ( imageBytes,options, reqWidth, reqHeight);            imageBytes = null;            return bitmapToDisplay;        }    }}
Xamarin image download and resizing for Android
c#;android;xamarin