0

皆さんからの助けが必要です。いくつかの Web 画像を含む 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

簡単な(おそらく最適ではない)解決策を見つけました。私が使用したトリックは、最後の n 個の有効な画像 URL を格納する Queue オブジェクトです。n は画面に表示可能な単語の数です。セルが再利用されると、最後の画像の URL がキューから取り出され、それが表示されようとしているときに、それがキューにあるかどうかを確認し、そうでない場合は拒否します。

于 2012-10-05T15:35:57.477 に答える