public static async Task ApplyDrawableAsync(this IVisualElementRenderer renderer,
                                                    BindableObject bindable,
                                                    BindableProperty imageSourceProperty,
                                                    Context context,
                                                    Action <Drawable> onSet,
                                                    Action <bool> onLoading             = null,
                                                    CancellationToken cancellationToken = default(CancellationToken))
        {
            _ = context ?? throw new ArgumentNullException(nameof(context));
            _ = imageSourceProperty ?? throw new ArgumentNullException(nameof(imageSourceProperty));
            _ = onSet ?? throw new ArgumentNullException(nameof(onSet));

            // make sure things are good before we start
            BindableObject element = null;

            if (!renderer.IsDrawableSourceValid(bindable, out element))
            {
                return;
            }

            onLoading?.Invoke(true);
            if (element.GetValue(imageSourceProperty) is ImageSource initialSource && !initialSource.IsEmpty)
            {
                try
                {
                    string cacheKey = String.Empty;

                    // Todo improve for other sources
                    // volley the requests better up front so that if the same request comes in it isn't requeued
                    if (initialSource is UriImageSource uri && uri.CachingEnabled)
                    {
                        cacheKey = Device.PlatformServices.GetMD5Hash(uri.Uri.ToString());
                        var cacheObject = await GetCache().GetAsync(cacheKey, uri.CacheValidity, async() =>
                        {
                            var drawable = await context.GetFormsDrawableAsync(initialSource, cancellationToken);
                            return(drawable);
                        });

                        Drawable returnValue = null;
                        if (cacheObject is Bitmap bitmap)
                        {
                            returnValue = new BitmapDrawable(context.Resources, bitmap);
                        }
                        else
                        {
                            returnValue = cacheObject as Drawable;
                        }

                        if (!renderer.IsDrawableSourceValid(bindable, out element))
                        {
                            return;
                        }

                        // only set if we are still on the same image
                        if (element.GetValue(imageSourceProperty) == initialSource)
                        {
                            using (returnValue)
                                onSet(returnValue);
                        }
                    }
                    else
                    {
                        using (var drawable = await context.GetFormsDrawableAsync(initialSource, cancellationToken))
                        {
                            if (!renderer.IsDrawableSourceValid(bindable, out element))
                            {
                                return;
                            }

                            // only set if we are still on the same image
                            if (element.GetValue(imageSourceProperty) == initialSource)
                            {
                                onSet(drawable);
                            }
                        }
                    }
                }