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