如何在ViewWillAppear中使用FFImageLoading?

时间:2017-11-19 13:39:34

标签: xamarin.ios uiimageview ffimageloading

我想在顶部栏中显示UIImageView,其中包含来自网址的UIImage,然后将其缓存在我的iOS原生Xamarin iOS应用中。问题是,当添加到 ViewWillAppear 时,FFImageLoading日志显示图像被取消大约9次中的10次,但偶尔会成功并显示。我用:

ImageService.Instance.LoadUrl(url)
                        .Retry(3, 200)
                        .Into(avatarImage);

它在第一次尝试时成功或者所有重试都失败了(我也尝试了更长的重试延迟而没有成功)。如果我将代码放在ViewDidAppear中,它可以在10次中工作9次,但并不总是从不首次加载。如果我把它放入一个按钮,我在视图加载后按下,图像总是成功加载。所以很明显FFImageLoading失败了,因为UIImageView还没有被绘制/加载,但是因为我创建了UIImageView并将其添加到View中我不知道还能做些什么。

如何使用FFImageLoading可靠地加载图像?我可以预加载它,但是在第一次显示它之前,我仍然没有解决它如何进入UIImageView的问题。如果FFImageLoading不可能,我可以选择替代方案。

日志:无法加载到UIImageView

[0:] FFImageLoadingDebug_SimpleDiskCache path: /var/mobile/Containers/Data/Application/93D1FA0C-B19A-4ECA-A0DA-B0AC408A5B8E/Library/Caches/FFSimpleDiskCache
Thread started: <Thread Pool> #3
Thread started: <Thread Pool> #4
Thread started: <Thread Pool> #5
Thread started: <Thread Pool> #6
Thread started:  #7
Thread started: <Thread Pool> #8
Thread started: <Thread Pool> #9
Thread started:  #10
Thread started:  #11
Thread started: <Thread Pool> #12
Thread started: <Thread Pool> #13
[0:] FFImageLoadingDebug_Image memory cache size: 401,5 MB
[0:] FFImageLoadingDebug_Image loading cancelled: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Generating/retrieving image: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Generating/retrieving image: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
Thread started:  #14
[0:] FFImageLoadingDebug_Wait for similar request for key: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
[0:] FFImageLoadingDebug_Image loading cancelled: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_File /var/mobile/Containers/Data/Application/93D1FA0C-B19A-4ECA-A0DA-B0AC408A5B8E/Library/Caches/FFSimpleDiskCache/CD275DFA133499968568338D6D522382.864000 saved to disk cache for key CD275DFA133499968568338D6D522382
[0:] FFImageLoadingDebug_Image loaded from cache: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
etc.

日志:成功(重新加载几次后的同一页面)

[0:] FFImageLoadingDebug_Image loaded from cache: https://assets-cdn.github.com/images/modules/logos_page/Octocat.png;CircleTransformation,borderSize=0,borderHexColor=
[0:] FFImageLoadingDebug_Image loaded from cache: https://autodesk-forge.github.io/dist/sample.png?43fa010fd5f9a49ec978f5dec499349d
etc.

2 个答案:

答案 0 :(得分:1)

请参阅official sample。这可能会有所帮助。

var taskImage = ImageService.Instance.LoadUrl(imageURL)
                                    .ErrorPlaceholder("error.png", ImageSource.ApplicationBundle)
                                    .LoadingPlaceholder("placeholder", ImageSource.CompiledResource);
if(transformation==0)
{
    taskImage.Into(imageView);
    transformation++;
}
else if(transformation==1)
{
    taskImage.Transform(new CircleTransformation()).Into(imageView);
    transformation++;
}
else if(transformation==2)
{
     taskImage.Transform(new RoundedTransformation(10)).Into(imageView);
     transformation = 0;
}

答案 1 :(得分:0)

我一直无法弄清楚为什么FFImageLoading被取消了,所以我使用Akavache和HttpClient来自己滚动(我也使用CrossConnectivity检查移动设备是否已连接)。

每次从ViewWillAppear更新时都可以使用。因为我使用IObservable,所以更新主UI线程上的图像非常重要,例如InvokeOnMainThread

UrlImageView类,用于添加可以从网址加载图片的UIView

public class UrlImageView : UIImageView
    {
        private GetImageFromUrlObserver getImageFromUrlObserver = null;

        public UrlImageView() : base()
        {
            getImageFromUrlObserver = new GetImageFromUrlObserver(this);
        }

        public void GetImageFromUrl(string url)
        {
            if (getImageFromUrlObserver != null)
            {
                getImageFromUrlObserver.GetImage(url);
            }
        }

        public void Update(byte[] image)
        {
            this.InvokeOnMainThread(() =>
            {
                var data = NSData.FromArray(image);
                this.Image = UIImage.LoadFromData(data);
            });            
        }
    }

IObserver类(检索图像数据时会触发OnNext

public class GetImageFromUrlObserver : IObserver<byte[]>
    {
        private UrlImageView urlImageView;
        private IDisposable unsubscriber;

        public GetImageFromUrlObserver(UrlImageView view)  
        {
            urlImageView = view;
        }

        public void GetImage(string url)
        {
            Subscribe(ImageLoader.GetImageFromUrl(url));
        }

        private void Subscribe(IObservable<byte[]> provider)
        {
            if (provider != null)
                unsubscriber = provider.Subscribe(this);
        }

        public void OnCompleted()
        {
            Unsubscribe();
        }

        public void OnError(Exception error)
        {
            throw new NotImplementedException();
        }

        public void OnNext(byte[] image)
        {    
            if (urlImageView != null)
            {
                urlImageView.Update(image);
            }
        }

        private void Unsubscribe()
        {
            if (unsubscriber != null)
            {
                urlImageView = null;
                unsubscriber.Dispose();
                unsubscriber = null;
            }            
        }
    }

获取图片数据的HttpClient类

public static class ImageLoader
{
        public static IObservable<byte[]> GetImageFromUrl(string url)
        {
             IObservable<byte[]> result = null;
             var httpClient = new HttpClient(new NativeMessageHandler());
        });

        try
            {
                    var cache = BlobCache.LocalMachine;
                    result = cache.GetAndFetchLatest(
                    url, /* simply use url as cache key */
                    async () =>
                    {
                        try
                        {
                            if (!CrossConnectivity.Current.IsConnected) return null;
                            HttpResponseMessage httpResponse = await httpClient.GetAsync(url);
                            return await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); ;
                        }
                        catch (Exception e)
                        {
                            EventTrackers.TrackException("GetImageFromUrl inner - " + e.Message);
                            return null;
                        }
                    },
                    offset =>
                    {
                        TimeSpan elapsed = DateTimeOffset.Now - offset;                            
                        return elapsed > new TimeSpan(hours: cacheUpdateFrequencyHours, minutes: cacheUpdateFrequencyMinutes, seconds: 0);
                    }
                );

            }
            catch (Exception e)
            {
                EventTrackers.TrackException("GetImageFromUrl - " + e.Message);
                return null;
            }

            return result;
}

显示您致电的图片

UrlImageView image = new UrlImageView();
View.AddSubview(image);
image.GetImageFromUrl(url);