c# - 如何回收/重用子视图列表而不必重新计算大小以获得更好的性能?Xamarin 表单
问题描述
我目前正在使用具有列表支持的 Stacklayout。我将此列表的数据加载到另一个线程上,然后将其添加到主线程上的此视图中。这在功能方面工作得很好,但是当项目被加载到控件时我遇到了轻微的延迟/性能问题。因此,在调用 API 之后,对主线程的分配正在发生。我加载了大约 5 个项目以确保我不会拥挤它,因为它包含图像(尺寸小 + 我使用 FFImageLoading)。
我现在所做的是缓存所有视图,然后在可能的情况下重用它。工作正常,但似乎并没有提高性能。我想的是覆盖LayoutChildren
,因为即使我重用视图,添加到此堆栈布局的子项似乎也在重新计算它的大小。我可能做错了什么?
下面是我的自定义控件:
public class CustomStackLayout : StackLayout
{
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(CustomStackLayout),
default(DataTemplate), BindingMode.OneWay);
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set
{
SetValue(ItemTemplateProperty, value);
OnPropertyChanged(nameof(ItemTemplate));
}
}
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(CustomStackLayout), default(IEnumerable<object>), BindingMode.TwoWay, propertyChanged: ItemsSourceChanged);
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set
{
SetValue(ItemsSourceProperty, value);
OnPropertyChanged(nameof(ItemsSource));
}
}
private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
{
var items = (CustomStackLayout)bindable;
items.Children.Clear();
if (items.ItemsSource != null)
{
foreach (var item in items.ItemsSource)
{
items.Children.Add(items.GetRowView(item));
}
}
}
protected virtual View GetRowView(object item)
{
// See if cached
var model = item as CustomModel;
if (AllViews.Any(x => x.Message.ObjectID.Equals(model.ObjectID)))
{
return AllViews.Where(x => x.Message.ObjectID.Equals(model.ObjectID)).FirstOrDefault().View;
}
object viewContent;
// Determine if this is a straight up template or using a AllViewselector
if (ItemTemplate is DataTemplateSelector dts)
{
var template = dts.SelectTemplate(item, this);
viewContent = template.CreateContent();
}
else
{
viewContent = ItemTemplate.CreateContent();
}
// Cache views
this.AllViews.Add(new CachedView() { Message = msg, View = viewContent is View ? viewContent as View : ((ViewCell)viewContent).View });
// Bind
var rowView = viewContent is View ? viewContent as View : ((ViewCell)viewContent).View;
rowView.BindingContext = item;
return rowView;
}
public List<CachedView> AllViews = new List<CachedView>();
}
public class CachedView
{
public Type Type { get; set; }
public View View { get; set; }
public Message Message { get; set; }
}
这就是我在 xaml 中使用它的方式,它DataTemplateSelector
根据数据在不同的视图之间进行选择:
<controls:CustomStackLayout ItemsSource="{Binding Data}">
<controls:CustomStackLayout.ItemTemplate>
<selector:MyDataTemplateSelector />
</controls:CustomStackLayout.ItemTemplate>
</controls:CustomStackLayout>
解决方案
推荐阅读
- video - 试图在谷歌上制作视频自动播放,但我不能
- c# - 我可以像服务一样记录所有作业(文档)来在 c# 中打印吗?
- java - 标记中的图形丢失质量
- graphql - 如何使用 GraphQL 获取 GitHub 存储库的提交以及已更改的文件和更改本身
- c++ - 填充类向量,同时将行为与数据分离
- django - 需要在 python/django 中通过浏览器识别用户?
- windows - 如何在 Windows 操作系统中创建自定义事件?
- python - 删除 PySpark 数据框列中的最后几个字符
- class-diagram - 多次使用类实例的模型组合
- umbraco - Umbraco,列出媒体文件,按大小排序