0

我需要你们的帮助。我有一个包含一些网络图像的 Monotouch UITableView。我已经实现了一个异步获取它们的任务,因此 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();
        }
    }
}

这是包含自定义单元格的 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
    }
}

非常感谢所有帮助

4

1 回答 1

0

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

于 2012-10-05T15:35:57.477 回答