【问题标题】:How to use FFImageLoading in ViewWillAppear?如何在 ViewWillAppear 中使用 FFImageLoading?
【发布时间】:2017-11-23 17:37:39
【问题描述】:

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

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

它要么在第一次尝试时成功,要么所有重试都失败(我也尝试过更长的重试延迟但没有成功)。如果我将代码放在 ViewDidAppear 中,它会在 10 次中工作 9 次,但并非总是如此,也不会在第一次加载时工作。如果我将它放入在视图加载后按下的按钮中,则图像始终会成功加载。因此,FFImageLoading 失败似乎很明显,因为 UIImageView 尚未被绘制/加载,但是当我创建 UIImageView 并将其添加到视图中时,我不知道我还能做什么。

如何使用 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.

【问题讨论】:

    标签: xamarin.ios uiimageview ffimageloading


    【解决方案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;
    }
    

    【讨论】:

    • 谢谢,我已经很久没有看它了,它确认我做的一切都是正确的(我测试了将 UIImage 设置为 null 但没有区别)。所以我更加困惑为什么图像没有加载到 UIImageView 中。我已经添加了日志以防万一。请注意,所有其他 FFImageLoading 图像都可以正常加载 - 尽管它们是在后台线程上完成的,所以稍后再触发。
    • @Tarostar 尝试使用SDWebImage 而不是FFImageLoading
    【解决方案2】:

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

    每次从 ViewWillAppear 更新时都有效。因为我使用 IObservable,所以更新主 UI 线程上的图像很重要,即InvokeOnMainThread

    UrlImageView 类用于添加可以从 Url 加载图像的 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);
    

    【讨论】:

      猜你喜欢
      • 2018-03-06
      • 1970-01-01
      • 2018-04-15
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多