Xamarin.ios Monotouch UITableView图像“;闪烁;当后台请求被提取时

Xamarin.ios Monotouch UITableView图像“;闪烁;当后台请求被提取时,xamarin.ios,Xamarin.ios,我需要你们的帮助。我有一个Monotouch UITableView,其中包含一些web图像。我已经实现了一个异步获取它们的任务,因此UI具有响应性,甚至还添加了一些动画,以便在从web获取它们时淡入淡出 当用户在UITableView中快速向下滚动时,我的问题就开始了,因此,由于单元格是可恢复的,所以有几个后台任务排队等待图像。当他位于列表底部时,他可能会看到缩略图显示另一个单元格的图像,然后是另一个单元格,然后是另一个单元格,然后是另一个单元格,因为任务完成后,每个图像都会替换另一个单元格。

我需要你们的帮助。我有一个Monotouch UITableView,其中包含一些web图像。我已经实现了一个异步获取它们的任务,因此UI具有响应性,甚至还添加了一些动画,以便在从web获取它们时淡入淡出

当用户在UITableView中快速向下滚动时,我的问题就开始了,因此,由于单元格是可恢复的,所以有几个后台任务排队等待图像。当他位于列表底部时,他可能会看到缩略图显示另一个单元格的图像,然后是另一个单元格,然后是另一个单元格,然后是另一个单元格,因为任务完成后,每个图像都会替换另一个单元格。我需要检查当前显示的单元格是否与正确的图像url对应,但不确定如何执行

下面是我的TableSource类的代码

using System;
using MonoTouch.UIKit;
using MonoTouch.Foundation;
using System.Collections.Generic; 
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

{
    public class ListDelegate:UITableViewDelegate
    {
        private UINavigationController nav;
        public override float GetHeightForRow (UITableView tableView, NSIndexPath indexPath)
        {
            return 128;
        }
        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            DealViewController c = new DealViewController(((ListDataSource)tableView.DataSource).deals[indexPath.Row].Id,nav);
            nav.PushViewController(c,true);
            tableView.DeselectRow(indexPath,true);
        }
        public ListDelegate(UINavigationController nav)
        {
            this.nav = nav;
        }
    }
    public class ListDataSource:UITableViewDataSource
    {
        bool toggle=true;
        Dictionary<string,UIImage> images = new Dictionary<string, UIImage>();
        public List<MyDeal> deals = new List<MyDeal>();
        Dictionary<int,ListCellViewController> controllers = new Dictionary<int, ListCellViewController>();
        public ListDataSource(List<MyDeal> deals)
        {
            this.deals = deals;
        }
        public override int RowsInSection (UITableView tableview, int section)
        {
            return deals.Count;
        }
        public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
        {
            UITableViewCell cell = tableView.DequeueReusableCell("cell");
            ListCellViewController cellController = null;
             if (cell == null || !controllers.ContainsKey(cell.Tag))
             {
                cellController = new ListCellViewController();
                NSBundle.MainBundle.LoadNib("ListCellViewController", cellController, null);
                cell = cellController.Cell;
                cell.Tag = Environment.TickCount;
                controllers.Add(cell.Tag, cellController);
             }
             else
             {
                cellController = controllers[cell.Tag];
             }
            if (toggle)
            {
                cell.BackgroundView = new UIImageView(UIImage.FromFile("images/bg1.jpg"));
            }
            else
            {
                cell.BackgroundView = new UIImageView(UIImage.FromFile("images/bg2.jpg"));
            }
            toggle = !toggle;
            MyDeal d = deals[indexPath.Row];
            cellController.SetValues(d.Title,d.Price,d.Value,d.DiscountPercent);
            GetImage(cellController.Thumbnail,d.Thumbnail);
            return cell;
        }
        private void GetImage(UIImageView img, string url)
        {
            img.Alpha = 0;
            if (url != string.Empty)
            {
                if (images.ContainsKey(url))
                {
                    img.Image = images[url];
                    img.Alpha = 1;
                }
                else
                {
                    var context = TaskScheduler.FromCurrentSynchronizationContext ();
                    Task.Factory.StartNew (() => {
                        NSData imageData = NSData.FromUrl(new NSUrl(url));
                        var uimg = UIImage.LoadFromData(imageData);
                        images.Add(url,uimg);
                        return uimg;
                    }).ContinueWith (t => { 
                        InvokeOnMainThread(()=>{
                            img.Image = t.Result;
                            RefreshImage(img);
                        });             
                    }, context);
                }
            }
        }
        private void RefreshImage(UIImageView img)
        {
            UIView.BeginAnimations("imageThumbnailTransitionIn");
            UIView.SetAnimationDuration(0.5f);
            img.Alpha = 1.0f;
            UIView.CommitAnimations();
        }
    }
}

非常感谢所有帮助

我找到了一个简单(可能不是最佳)的解决方案。我使用的技巧是一个队列对象来存储最后n个有效的图像URL,其中n是屏幕上可显示的字数。一旦一个单元格被重复使用,最后一个图像url将退出队列,当它即将显示时,我会检查它是否在队列中,如果不是,我会拒绝它。

有趣的是,我正在同时构建一个非常相似的东西。我喜欢你的代码,如果我能帮上忙,我会很高兴的。不过我刚刚开始monotouch开发。我还缺少您正在使用的ListCellViewController。你能把代码也发出来吗?
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;


{
    public partial class ListCellViewController : UIViewController
    {
        #region Constructors

        // The IntPtr and initWithCoder constructors are required for items that need 
        // to be able to be created from a xib rather than from managed code

        public ListCellViewController (IntPtr handle) : base(handle)
        {
            Initialize ();
        }

        [Export("initWithCoder:")]
        public ListCellViewController (NSCoder coder) : base(coder)
        {
            Initialize ();
        }

        public ListCellViewController () : base("ListCellViewController", null)
        {
            Initialize ();
        }

        void Initialize ()
        {
        }
        public UIImageView Thumbnail
        {
            get{return thumbnailView;}
        }
        public UITableViewCell Cell
        {
            get {return cell;}
        }
        public void SetValues(string title,decimal price,decimal valuex,decimal discount,int purchases)
        {

        }
        #endregion
    }
}