示例#1
0
        /// <summary>
        /// Loads the image from given stream asynchronously.
        /// </summary>
        /// <returns>An awaitable task.</returns>
        /// <param name="stream">The stream to get data from.</param>
        public override async Task <GenerateResult> LoadFromStreamAsync(Stream stream)
        {
            if (stream == null)
            {
                return(GenerateResult.Failed);
            }

            if (IsCancelled)
            {
                return(GenerateResult.Canceled);
            }

            var imageView = GetAttachedImageView();

            if (imageView == null || imageView.Handle == IntPtr.Zero)
            {
                return(GenerateResult.InvalidTarget);
            }

            var resultWithDrawable = await GetDrawableAsync("Stream", ImageSource.Stream, false, false, stream).ConfigureAwait(false);

            if (resultWithDrawable.HasError)
            {
                // Show error placeholder
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                return(resultWithDrawable.GenerateResult);
            }

            if (CanUseMemoryCache())
            {
                ImageCache.Instance.Add(GetKey(), resultWithDrawable.ImageInformation, resultWithDrawable.Item);
            }

            try
            {
                if (IsCancelled)
                {
                    return(GenerateResult.Canceled);
                }

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    SetImageDrawable(imageView, resultWithDrawable.Item);

                    Completed = true;
                    Parameters?.OnSuccess(resultWithDrawable.ImageInformation, resultWithDrawable.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                // Show error placeholder
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
        /// <summary>
        /// Tries to load requested image from the cache asynchronously.
        /// </summary>
        /// <returns>A boolean indicating if image was loaded from cache.</returns>
        public override async Task <CacheResult> TryLoadingFromCacheAsync()
        {
            try
            {
                if (!_target.IsValid)
                {
                    return(CacheResult.NotFound);                    // weird situation, dunno what to do
                }
                if (IsCancelled)
                {
                    return(CacheResult.NotFound);                    // not sure what to return in that case
                }
                var key = GetKey();

                if (string.IsNullOrWhiteSpace(key))
                {
                    return(CacheResult.NotFound);
                }

                var cacheEntry = ImageCache.Instance.Get(key);

                if (cacheEntry == null)
                {
                    return(CacheResult.NotFound);                    // not available in the cache
                }
                var value = cacheEntry.Item1;

                if (value == null)
                {
                    return(CacheResult.NotFound);                    // not available in the cache
                }
                if (IsCancelled)
                {
                    return(CacheResult.NotFound);                    // not sure what to return in that case
                }
                value.SetIsRetained(true);

                try
                {
                    Logger.Debug(string.Format("Image from cache: {0}", key));
                    await MainThreadDispatcher.PostAsync(() =>
                    {
                        if (IsCancelled)
                        {
                            return;
                        }

                        var ffDrawable = value as FFBitmapDrawable;
                        if (ffDrawable != null)
                        {
                            ffDrawable.StopFadeAnimation();
                        }

                        _target.Set(this, value, true, false);

                        Completed = true;

                        Parameters?.OnSuccess(cacheEntry.Item2, LoadingResult.MemoryCache);
                    }).ConfigureAwait(false);

                    if (!Completed)
                    {
                        return(CacheResult.NotFound);             // not sure what to return in that case
                    }
                    return(CacheResult.Found);                    // found and loaded from cache
                }
                finally
                {
                    value.SetIsRetained(false);
                }
            }
            catch (Exception ex)
            {
                Parameters?.OnError(ex);
                return(CacheResult.ErrorOccured);                // weird, what can we do if loading from cache fails
            }
        }
示例#3
0
        /// <summary>
        /// Runs the image loading task: gets image from file, url, asset or cache. Then assign it to the imageView.
        /// </summary>
        protected override async Task <GenerateResult> TryGeneratingImageAsync()
        {
            WithLoadingResult <SelfDisposingBitmapDrawable> drawableWithResult;

            if (string.IsNullOrWhiteSpace(Parameters.Path))
            {
                drawableWithResult = new WithLoadingResult <SelfDisposingBitmapDrawable>(LoadingResult.Failed);
            }
            else
            {
                try
                {
                    drawableWithResult = await RetrieveDrawableAsync(Parameters.Path, Parameters.Source, false, false).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.Error("An error occured while retrieving drawable.", ex);
                    drawableWithResult = new WithLoadingResult <SelfDisposingBitmapDrawable>(LoadingResult.Failed);
                }
            }

            var imageView = GetAttachedImageView();

            if (imageView == null || imageView.Handle == IntPtr.Zero)
            {
                return(GenerateResult.InvalidTarget);
            }

            if (drawableWithResult.HasError)
            {
                // Show error placeholder
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                return(drawableWithResult.GenerateResult);
            }

            try
            {
                if (IsCancelled)
                {
                    return(GenerateResult.Canceled);
                }

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    SetImageDrawable(imageView, drawableWithResult.Item);

                    Completed = true;
                    Parameters?.OnSuccess(drawableWithResult.ImageInformation, drawableWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#4
0
        public async Task RunAsync()
        {
            LoadingResult loadingResult = LoadingResult.Failed;
            bool          success       = false;

            try
            {
                // LOAD IMAGE
                if (!(await TryLoadFromMemoryCacheAsync().ConfigureAwait(false)))
                {
                    if (Parameters.DelayInMs.HasValue && Parameters.DelayInMs.Value > 0)
                    {
                        await Task.Delay(Parameters.DelayInMs.Value).ConfigureAwait(false);
                    }
                    else if (!Parameters.Preload && Configuration.DelayInMs > 0)
                    {
                        await Task.Delay(Configuration.DelayInMs).ConfigureAwait(false);
                    }

                    Logger.Debug(string.Format("Generating/retrieving image: {0}", Key));
                    var resolver = Parameters.CustomDataResolver ?? DataResolverFactory.GetResolver(Parameters.Path, Parameters.Source, Parameters, Configuration);
                    resolver = new WrappedDataResolver(resolver);
                    var imageData = await resolver.Resolve(Parameters.Path, Parameters, CancellationTokenSource.Token).ConfigureAwait(false);

                    loadingResult = imageData.LoadingResult;

                    ImageInformation = imageData.ImageInformation;
                    ImageInformation.SetKey(Key, Parameters.CustomCacheKey);
                    ImageInformation.SetPath(Parameters.Path);
                    ThrowIfCancellationRequested();

                    // Preload
                    if (Parameters.Preload && Parameters.CacheType.HasValue && Parameters.CacheType.Value == CacheType.Disk)
                    {
                        if (loadingResult == LoadingResult.Internet)
                        {
                            Logger?.Debug(string.Format("DownloadOnly success: {0}", Key));
                        }

                        success = true;

                        return;
                    }

                    ThrowIfCancellationRequested();

                    TImageContainer image;

                    if (imageData.Stream != null)
                    {
                        using (imageData.Stream)
                        {
                            image = await GenerateImageAsync(Parameters.Path, Parameters.Source, imageData.Stream, imageData.ImageInformation, true, false).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        image = await GenerateImageAsync(Parameters.Path, Parameters.Source, imageData.Decoded, imageData.ImageInformation, true, false).ConfigureAwait(false);
                    }

                    ThrowIfCancellationRequested();

                    try
                    {
                        BeforeLoading(image, false);

                        if (image != default(TImageContainer) && CanUseMemoryCache)
                        {
                            MemoryCache.Add(Key, imageData.ImageInformation, image);
                        }

                        ThrowIfCancellationRequested();

                        bool isFadeAnimationEnabled = Parameters.FadeAnimationEnabled ?? Configuration.FadeAnimationEnabled;

                        if (Target != null)
                        {
                            await SetTargetAsync(image, isFadeAnimationEnabled).ConfigureAwait(false);
                        }
                    }
                    finally
                    {
                        AfterLoading(image, false);
                    }
                }

                success = true;
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException || ex is ObjectDisposedException)
                {
                    if (Configuration.VerboseLoadingCancelledLogging)
                    {
                        Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
                    }
                }
                else
                {
                    if (Configuration.ClearMemoryCacheOnOutOfMemory && ex is OutOfMemoryException)
                    {
                        MemoryCache.Clear();
                    }

                    Logger.Error(string.Format("Image loading failed: {0}", Key), ex);

                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnError != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnError?.Invoke(ex);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        Parameters?.OnError?.Invoke(ex);
                    }

                    try
                    {
                        // Error placeholder if enabled
                        if (!Parameters.Preload && !string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath))
                        {
                            await ShowPlaceholder(Parameters.ErrorPlaceholderPath, KeyForErrorPlaceholder,
                                                  Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex2)
                    {
                        if (!(ex2 is OperationCanceledException))
                        {
                            Logger.Error(string.Format("Image loading failed: {0}", Key), ex);
                        }
                    }
                }
            }
            finally
            {
                try
                {
                    if (CancellationTokenSource?.IsCancellationRequested == false)
                    {
                        CancellationTokenSource.Cancel();
                    }
                }
                catch (Exception)
                {
                }

                IsCompleted = true;

                using (Parameters)
                {
                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnFinish != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            if (success)
                            {
                                Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                            }
                            Parameters?.OnFinish?.Invoke(this);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        if (success)
                        {
                            Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                        }
                        Parameters?.OnFinish?.Invoke(this);
                    }

                    ImageService.RemovePendingTask(this);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Runs the image loading task: gets image from file, url, asset or cache. Then assign it to the imageView.
        /// </summary>
        protected override async Task <GenerateResult> TryGeneratingImageAsync()
        {
            WithLoadingResult <UIImage> imageWithResult = null;
            UIImage image = null;

            try
            {
                imageWithResult = await RetrieveImageAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);

                image = imageWithResult == null ? null : imageWithResult.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                image = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                return(GenerateResult.Failed);
            }

            if (CancellationToken.IsCancellationRequested)
            {
                return(GenerateResult.Canceled);
            }

            if (_getNativeControl() == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            try
            {
                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    _doWithImage(image, false);
                    Completed = true;
                    Parameters.OnSuccess(new ImageSize((int)image.Size.Width, (int)image.Size.Height), imageWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#6
0
        /// <summary>
        /// Loads given placeHolder into the imageView.
        /// </summary>
        /// <returns>An awaitable task.</returns>
        /// <param name="placeholderPath">Full path to the placeholder.</param>
        /// <param name="source">Source for the path: local, web, assets</param>
        protected async Task <bool> LoadPlaceHolderAsync(string placeholderPath, ImageSource source, ImageView imageView, bool isLoadingPlaceholder)
        {
            if (string.IsNullOrWhiteSpace(placeholderPath))
            {
                return(false);
            }

            if (imageView == null)
            {
                return(false);
            }

            var cacheEntry = ImageCache.Instance.Get(GetKey(placeholderPath));

            BitmapDrawable drawable = cacheEntry == null ? null: cacheEntry.Item1;

            if (drawable != null && drawable.Handle != IntPtr.Zero &&
                drawable.Bitmap != null && drawable.Bitmap.Handle != IntPtr.Zero && !drawable.Bitmap.IsRecycled)
            {
                // We should wrap drawable in an AsyncDrawable, nothing is deferred
                drawable = new SelfDisposingAsyncDrawable(Context.Resources, drawable.Bitmap, this);
            }
            else
            {
                // Here we asynchronously load our placeholder: it is deferred so we need a temporary AsyncDrawable
                drawable = new AsyncDrawable(Context.Resources, null, this);
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (imageView.Handle == IntPtr.Zero)
                    {
                        return;
                    }

                    imageView.SetImageDrawable(drawable);                     // temporary assign this AsyncDrawable
                }).ConfigureAwait(false);

                try
                {
                    var drawableWithResult = await RetrieveDrawableAsync(placeholderPath, source, isLoadingPlaceholder, true).ConfigureAwait(false);

                    drawable = drawableWithResult.Item;
                }
                catch (Exception ex)
                {
                    Logger.Error("An error occured while retrieving drawable.", ex);
                    return(false);
                }
            }

            if (drawable == null)
            {
                return(false);
            }

            _loadingPlaceholderWeakReference = new WeakReference <BitmapDrawable>(drawable);

            if (IsCancelled)
            {
                return(false);
            }

            await MainThreadDispatcher.PostAsync(() =>
            {
                if (IsCancelled)
                {
                    return;
                }

                if (imageView.Handle == IntPtr.Zero)
                {
                    return;
                }

                SetImageDrawable(imageView, drawable);
            }).ConfigureAwait(false);

            return(true);
        }
示例#7
0
        public async virtual Task <bool> TryLoadFromMemoryCacheAsync()
        {
            try
            {
                if (Parameters.Preload && Parameters.CacheType.HasValue &&
                    (Parameters.CacheType.Value == CacheType.Disk || Parameters.CacheType.Value == CacheType.None))
                {
                    return(false);
                }

                ThrowIfCancellationRequested();

                bool isFadeAnimationEnabledForCached = Parameters.FadeAnimationForCachedImagesEnabled.HasValue ? Parameters.FadeAnimationForCachedImagesEnabled.Value : Configuration.FadeAnimationForCachedImages;
                var  result = await TryLoadFromMemoryCacheAsync(Key, true, isFadeAnimationEnabledForCached, false).ConfigureAwait(false);

                if (result)
                {
                    Logger.Debug(string.Format("Image loaded from cache: {0}", Key));
                    IsCompleted = true;

                    if (Configuration.ExecuteCallbacksOnUIThread && (Parameters?.OnSuccess != null || Parameters?.OnFinish != null))
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnSuccess?.Invoke(ImageInformation, LoadingResult.MemoryCache);
                            Parameters?.OnFinish?.Invoke(this);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        Parameters?.OnSuccess?.Invoke(ImageInformation, LoadingResult.MemoryCache);
                        Parameters?.OnFinish?.Invoke(this);
                    }
                }
                else
                {
                    ThrowIfCancellationRequested();
                    // Loading placeholder if enabled
                    if (!_isLoadingPlaceholderLoaded && !string.IsNullOrWhiteSpace(Parameters.LoadingPlaceholderPath))
                    {
                        await ShowPlaceholder(Parameters.LoadingPlaceholderPath, KeyForLoadingPlaceholder,
                                              Parameters.LoadingPlaceholderSource, true).ConfigureAwait(false);
                    }
                }

                return(result);
            }
            catch (Exception ex)
            {
                if (Configuration.ClearMemoryCacheOnOutOfMemory && ex is OutOfMemoryException)
                {
                    MemoryCache.Clear();
                }

                if (ex is OperationCanceledException)
                {
                    if (Configuration.VerboseLoadingCancelledLogging)
                    {
                        Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
                    }
                }
                else
                {
                    Logger.Error(string.Format("Image loading failed: {0}", Key), ex);

                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnError != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnError?.Invoke(ex);
                        }).ConfigureAwait(false);
                    }
                    else
                    {
                        Parameters?.OnError?.Invoke(ex);
                    }
                }
            }

            return(false);
        }
示例#8
0
        public override async Task <GenerateResult> LoadFromStreamAsync(Stream stream)
        {
            if (stream == null)
            {
                return(GenerateResult.Failed);
            }

            if (IsCancelled)
            {
                return(GenerateResult.Canceled);
            }

            WithLoadingResult <WriteableBitmap> resultWithImage;
            WriteableBitmap image = null;

            try
            {
                resultWithImage = await GetImageAsync("Stream", ImageSource.Stream, false, stream).ConfigureAwait(false);

                image = resultWithImage.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                resultWithImage = new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed);
                image           = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);

                return(resultWithImage.GenerateResult);
            }

            if (CanUseMemoryCache())
            {
                ImageCache.Instance.Add(GetKey(), resultWithImage.ImageInformation, image);
            }

            if (IsCancelled)
            {
                return(GenerateResult.Canceled);
            }

            if (_getNativeControl() == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            try
            {
                int pixelWidth  = 0;
                int pixelHeight = 0;

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (IsCancelled)
                    {
                        return;
                    }

                    _doWithImage(image, true, false);
                    pixelWidth  = image.PixelWidth;
                    pixelHeight = image.PixelHeight;
                    Completed   = true;
                    Parameters?.OnSuccess(resultWithImage.ImageInformation, resultWithImage.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#9
0
        protected override async Task <GenerateResult> TryGeneratingImageAsync()
        {
            WithLoadingResult <WriteableBitmap> imageWithResult;
            WriteableBitmap image = null;

            try
            {
                imageWithResult = await RetrieveImageAsync(Parameters.Path, Parameters.Source, false).ConfigureAwait(false);

                image = imageWithResult.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                imageWithResult = new WithLoadingResult <WriteableBitmap>(LoadingResult.Failed);
                image           = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);

                return(imageWithResult.GenerateResult);
            }

            if (IsCancelled)
            {
                return(GenerateResult.Canceled);
            }

            if (_getNativeControl() == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            try
            {
                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (IsCancelled)
                    {
                        return;
                    }

                    _doWithImage(image, imageWithResult.Result.IsLocalOrCachedResult(), false);
                    Completed = true;
                    Parameters?.OnSuccess(imageWithResult.ImageInformation, imageWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#10
0
        public override async Task <GenerateResult> LoadFromStreamAsync(Stream stream, bool isPlaceholder)
        {
            if (stream == null)
            {
                return(GenerateResult.Failed);
            }

            if (CancellationToken.IsCancellationRequested)
            {
                return(GenerateResult.Canceled);
            }

            WithLoadingResult <WriteableBitmap> imageWithResult = null;
            WriteableBitmap image = null;

            try
            {
                imageWithResult = await GetImageAsync("Stream", ImageSource.Stream, isPlaceholder, stream).ConfigureAwait(false);

                image = imageWithResult == null ? null : imageWithResult.Item;
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                image = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                return(GenerateResult.Failed);
            }

            if (CancellationToken.IsCancellationRequested)
            {
                return(GenerateResult.Canceled);
            }

            if (_getNativeControl() == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            try
            {
                int pixelWidth  = 0;
                int pixelHeight = 0;

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    _doWithImage(image, false);
                    pixelWidth  = image.PixelWidth;
                    pixelHeight = image.PixelHeight;
                    Completed   = true;
                    Parameters.OnSuccess(new ImageSize(pixelWidth, pixelHeight), imageWithResult.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#11
0
        protected virtual async Task <WithLoadingResult <WriteableBitmap> > GetImageAsync(string sourcePath, ImageSource source,
                                                                                          bool isPlaceholder, Stream originalStream = null)
        {
            if (CancellationToken.IsCancellationRequested)
            {
                return(null);
            }

            byte[]        bytes  = null;
            string        path   = sourcePath;
            LoadingResult?result = null;

            try
            {
                if (originalStream != null)
                {
                    using (var ms = new MemoryStream())
                    {
                        await originalStream.CopyToAsync(ms).ConfigureAwait(false);

                        bytes  = ms.ToArray();
                        path   = sourcePath;
                        result = LoadingResult.Stream;
                    }
                }
                else
                {
                    using (var resolver = DataResolverFactory.GetResolver(source, Parameters, DownloadCache))
                    {
                        var data = await resolver.GetData(path, CancellationToken.Token).ConfigureAwait(false);

                        if (data == null)
                        {
                            return(null);
                        }

                        bytes  = data.Data;
                        path   = data.ResultIdentifier;
                        result = data.Result;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                Logger.Debug(string.Format("Image request for {0} got cancelled.", path));
                return(null);
            }
            catch (Exception ex)
            {
                var message = String.Format("Unable to retrieve image data from source: {0}", sourcePath);
                Logger.Error(message, ex);
                Parameters.OnError(ex);
                return(null);
            }

            if (bytes == null)
            {
                return(null);
            }

            var image = await Task.Run(async() =>
            {
                if (CancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                WriteableBitmap writableBitmap = null;

                // Special case to handle WebP decoding
                if (sourcePath.ToLowerInvariant().EndsWith(".webp"))
                {
                    //TODO
                    throw new NotImplementedException("Webp is not implemented on Windows");
                }

                bool transformPlaceholdersEnabled = Parameters.TransformPlaceholdersEnabled.HasValue ?
                                                    Parameters.TransformPlaceholdersEnabled.Value : ImageService.Config.TransformPlaceholders;

                if (Parameters.Transformations != null && Parameters.Transformations.Count > 0 &&
                    (!isPlaceholder || (isPlaceholder && transformPlaceholdersEnabled)))
                {
                    BitmapHolder imageIn = await bytes.ToBitmapHolderAsync(Parameters.DownSampleSize, Parameters.DownSampleInterpolationMode).ConfigureAwait(false);

                    foreach (var transformation in Parameters.Transformations.ToList() /* to prevent concurrency issues */)
                    {
                        if (CancellationToken.IsCancellationRequested)
                        {
                            return(null);
                        }

                        try
                        {
                            var old = imageIn;

                            IBitmap bitmapHolder = transformation.Transform(imageIn);
                            imageIn = bitmapHolder.ToNative();

                            // old = null;
                            // PLEASE NOTE! In Windows we could reuse int array (less memory usage) so we don't need that
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("Can't apply transformation " + transformation.Key + " to image " + path, ex);
                        }
                    }

                    await MainThreadDispatcher.PostAsync(async() =>
                    {
                        writableBitmap = await imageIn.ToBitmapImageAsync();
                    }).ConfigureAwait(false);
                }
                else
                {
                    writableBitmap = await bytes.ToBitmapImageAsync(Parameters.DownSampleSize, Parameters.DownSampleInterpolationMode).ConfigureAwait(false);
                }

                return(writableBitmap);
            }).ConfigureAwait(false);

            return(WithLoadingResult.Encapsulate(image, result.Value));
        }
示例#12
0
        /// <summary>
        /// Tries to load requested image from the cache asynchronously.
        /// </summary>
        /// <returns>A boolean indicating if image was loaded from cache.</returns>
        private async Task <CacheResult> TryLoadingFromCacheAsync(ImageView imageView)
        {
            try
            {
                if (imageView == null)
                {
                    return(CacheResult.NotFound);                    // weird situation, dunno what to do
                }
                if (IsCancelled)
                {
                    return(CacheResult.NotFound);                    // not sure what to return in that case
                }
                var key = GetKey();

                if (string.IsNullOrWhiteSpace(key))
                {
                    return(CacheResult.NotFound);
                }

                var value = ImageCache.Instance.Get(key);
                if (value == null)
                {
                    return(CacheResult.NotFound);                    // not available in the cache
                }
                if (IsCancelled)
                {
                    return(CacheResult.NotFound);                    // not sure what to return in that case
                }
                value.SetIsRetained(true);

                try
                {
                    Logger.Debug(string.Format("Image from cache: {0}", key));
                    await MainThreadDispatcher.PostAsync(() =>
                    {
                        if (IsCancelled)
                        {
                            return;
                        }

                        var ffDrawable = value as FFBitmapDrawable;
                        if (ffDrawable != null)
                        {
                            ffDrawable.StopFadeAnimation();
                        }

                        if (imageView == null || imageView.Handle == IntPtr.Zero)
                        {
                            return;
                        }

                        imageView.SetImageDrawable(value);

                        if (Utils.HasJellyBean() && imageView.AdjustViewBounds)
                        {
                            imageView.LayoutParameters.Height = value.IntrinsicHeight;
                            imageView.LayoutParameters.Width  = value.IntrinsicWidth;
                        }
                    }).ConfigureAwait(false);

                    if (IsCancelled)
                    {
                        return(CacheResult.NotFound);                        // not sure what to return in that case
                    }
                    Completed = true;

                    if (Parameters.OnSuccess != null)
                    {
                        Parameters.OnSuccess(new ImageSize(value.IntrinsicWidth, value.IntrinsicHeight), LoadingResult.MemoryCache);
                    }
                    return(CacheResult.Found);                    // found and loaded from cache
                }
                finally
                {
                    value.SetIsRetained(false);
                }
            }
            catch (Exception ex)
            {
                if (Parameters.OnError != null)
                {
                    Parameters.OnError(ex);
                }
                return(CacheResult.ErrorOccured);                // weird, what can we do if loading from cache fails
            }
        }
示例#13
0
        /// <summary>
        /// Loads the image from given stream asynchronously.
        /// </summary>
        /// <returns>An awaitable task.</returns>
        /// <param name="stream">The stream to get data from.</param>
        public override async Task <GenerateResult> LoadFromStreamAsync(Stream stream)
        {
            if (stream == null)
            {
                return(GenerateResult.Failed);
            }

            if (CancellationToken.IsCancellationRequested)
            {
                return(GenerateResult.Canceled);
            }

            var imageView = GetAttachedImageView();

            if (imageView == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            var resultWithDrawable = await GetDrawableAsync("Stream", ImageSource.Stream, false, false, stream).ConfigureAwait(false);

            if (resultWithDrawable == null || resultWithDrawable.Item == null)
            {
                // Show error placeholder
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                return(GenerateResult.Failed);
            }

            try
            {
                if (CancellationToken.IsCancellationRequested)
                {
                    return(GenerateResult.Canceled);
                }

                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    if (imageView == null || imageView.Handle == IntPtr.Zero)
                    {
                        return;
                    }

                    SetImageDrawable(imageView, resultWithDrawable.Item, UseFadeInBitmap);

                    Completed = true;
                    Parameters.OnSuccess(new ImageSize(resultWithDrawable.Item.IntrinsicWidth, resultWithDrawable.Item.IntrinsicHeight), resultWithDrawable.Result);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                // Show error placeholder
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource, imageView, false).ConfigureAwait(false);

                throw ex2;
            }

            return(GenerateResult.Success);
        }
示例#14
0
        protected async override Task SetTargetAsync(SelfDisposingBitmapDrawable image, bool animated)
        {
            if (Target == null)
            {
                return;
            }

            ThrowIfCancellationRequested();

            if (image is FFBitmapDrawable ffDrawable)
            {
                if (ffDrawable.IsFadeAnimationRunning)
                {
                    var mut = new FFBitmapDrawable(Context.Resources, ffDrawable.Bitmap, ffDrawable);
                    ffDrawable = mut as FFBitmapDrawable;
                    image      = ffDrawable;

                    // old hacky workaround
                    //await Task.Delay(ffDrawable.FadeDuration + 50).ConfigureAwait(false);
                }

                if (animated)
                {
                    SelfDisposingBitmapDrawable placeholderDrawable = null;
                    PlaceholderWeakReference?.TryGetTarget(out placeholderDrawable);

                    if (placeholderDrawable == null)
                    {
                        // Enable fade animation when no placeholder is set and the previous image is not null
                        var imageView = PlatformTarget.Control as ImageView;
                        placeholderDrawable = imageView?.Drawable as SelfDisposingBitmapDrawable;
                    }

                    var fadeDuration = Parameters.FadeAnimationDuration ?? Configuration.FadeAnimationDuration;

                    if (placeholderDrawable.IsValidAndHasValidBitmap())
                    {
                        placeholderDrawable?.SetIsRetained(true);
                        ffDrawable?.SetPlaceholder(placeholderDrawable, fadeDuration);
                        placeholderDrawable?.SetIsRetained(false);
                    }
                    else if (ffDrawable.IsValidAndHasValidBitmap())
                    {
                        var width  = ffDrawable.Bitmap.Width;
                        var height = ffDrawable.Bitmap.Height;
                        var bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);

                        using (var canvas = new Canvas(bitmap))
                            using (var paint = new Paint()
                            {
                                Color = _placeholderHelperColor
                            })
                            {
                                canvas.DrawRect(0, 0, width, height, paint);
                            }

                        ffDrawable?.SetPlaceholder(new SelfDisposingBitmapDrawable(Context.Resources, bitmap), fadeDuration);
                    }
                }
                else
                {
                    ffDrawable?.SetPlaceholder(null, 0);
                }
            }

            await MainThreadDispatcher.PostAsync(() =>
            {
                ThrowIfCancellationRequested();

                PlatformTarget.Set(this, image, animated);
            }).ConfigureAwait(false);
        }
示例#15
0
        /// <summary>
        /// Runs the image loading task: gets image from file, url, asset or cache. Then assign it to the imageView.
        /// </summary>
        protected override async Task <GenerateResult> TryGeneratingImageAsync()
        {
            UIImage image = null;

            try
            {
                image = await RetrieveImageAsync(Parameters.Path, Parameters.Source).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.Error("An error occured while retrieving image.", ex);
                image = null;
            }

            if (image == null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                return(GenerateResult.Failed);
            }

            if (CancellationToken.IsCancellationRequested)
            {
                return(GenerateResult.Canceled);
            }

            if (_getNativeControl() == null)
            {
                return(GenerateResult.InvalidTarget);
            }

            Exception trappedException = null;

            try
            {
                // Post on main thread
                await MainThreadDispatcher.PostAsync(() =>
                {
                    if (CancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    _doWithImage(image);
                    Completed = true;
                    Parameters.OnSuccess((int)image.Size.Width, (int)image.Size.Height);
                }).ConfigureAwait(false);

                if (!Completed)
                {
                    return(GenerateResult.Failed);
                }
            }
            catch (Exception ex2)
            {
                trappedException = ex2;                 // All this stupid stuff is necessary to compile with c# 5, since we can't await in a catch block...
            }

            // All this stupid stuff is necessary to compile with c# 5, since we can't await in a catch block...
            if (trappedException != null)
            {
                await LoadPlaceHolderAsync(Parameters.ErrorPlaceholderPath, Parameters.ErrorPlaceholderSource).ConfigureAwait(false);

                throw trappedException;
            }

            return(GenerateResult.Success);
        }
        public async Task RunAsync()
        {
            try
            {
                if (IsCompleted || IsCancelled || ImageService.ExitTasksEarly)
                {
                    throw new OperationCanceledException();
                }

                ThrowIfCancellationRequested();
                LoadingResult loadingResult = LoadingResult.Failed;

                // LOAD IMAGE
                if (!(await TryLoadFromMemoryCacheAsync().ConfigureAwait(false)))
                {
                    Logger.Debug(string.Format("Generating/retrieving image: {0}", Key));
                    var resolver  = DataResolverFactory.GetResolver(Parameters.Path, Parameters.Source, Parameters, Configuration);
                    var imageData = await resolver.Resolve(Parameters.Path, Parameters, CancellationTokenSource.Token).ConfigureAwait(false);

                    loadingResult = imageData.Item2;

                    using (imageData.Item1)
                    {
                        ImageInformation = imageData.Item3;
                        ThrowIfCancellationRequested();

                        // Preload
                        if (Parameters.Preload && Parameters.CacheType.HasValue && Parameters.CacheType.Value == CacheType.Disk)
                        {
                            if (Parameters.Source != ImageSource.Url)
                            {
                                throw new InvalidOperationException("DownloadOnly: Only Url ImageSource is supported.");
                            }

                            if (loadingResult == LoadingResult.Internet)
                            {
                                Logger?.Debug(string.Format("DownloadOnly success: {0}", Key));
                            }

                            if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnSuccess != null)
                            {
                                await MainThreadDispatcher.PostAsync(() =>
                                {
                                    Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                                });
                            }
                            else
                            {
                                Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                            }

                            return;
                        }

                        ThrowIfCancellationRequested();

                        var image = await GenerateImageAsync(Parameters.Path, Parameters.Source, imageData.Item1, imageData.Item3, TransformPlaceholders, false).ConfigureAwait(false);

                        try
                        {
                            BeforeLoading(image, false);

                            if (image != default(TImageContainer) && CanUseMemoryCache)
                            {
                                MemoryCache.Add(Key, imageData.Item3, image);
                            }

                            ThrowIfCancellationRequested();

                            bool isFadeAnimationEnabled = Parameters.FadeAnimationEnabled ?? Configuration.FadeAnimationEnabled;
                            await SetTargetAsync(image, isFadeAnimationEnabled).ConfigureAwait(false);
                        }
                        finally
                        {
                            AfterLoading(image, false);
                        }
                    }
                }

                if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnSuccess != null)
                {
                    await MainThreadDispatcher.PostAsync(() =>
                    {
                        Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                    });
                }
                else
                {
                    Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult);
                }
            }
            catch (Exception ex)
            {
                if (_clearCacheOnOutOfMemory && ex is OutOfMemoryException)
                {
                    MemoryCache.Clear();
                }

                if (ex is OperationCanceledException || ex is ObjectDisposedException)
                {
                    if (Configuration.VerboseLoadingCancelledLogging)
                    {
                        Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
                    }
                }
                else
                {
                    Logger.Error(string.Format("Image loading failed: {0}", Key), ex);

                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnError != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnError?.Invoke(ex);
                        });
                    }
                    else
                    {
                        Parameters?.OnError?.Invoke(ex);
                    }

                    try
                    {
                        // Error placeholder if enabled
                        if (!Parameters.Preload && !string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath))
                        {
                            await ShowPlaceholder(Parameters.ErrorPlaceholderPath, KeyForErrorPlaceholder,
                                                  Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex2)
                    {
                        if (!(ex2 is OperationCanceledException))
                        {
                            Logger.Error(string.Format("Image loading failed: {0}", Key), ex);
                        }
                    }
                }
            }
            finally
            {
                using (Parameters)
                {
                    if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnFinish != null)
                    {
                        await MainThreadDispatcher.PostAsync(() =>
                        {
                            Parameters?.OnFinish?.Invoke(this);
                        });
                    }
                    else
                    {
                        Parameters?.OnFinish?.Invoke(this);
                    }

                    ImageService.RemovePendingTask(this);
                }

                IsCompleted = true;
            }
        }