可以采取哪些步骤来优化ListView

时间:2016-08-19 11:25:22

标签: c# xamarin.forms

我有ObservableCollection绑定到ListView。此列表基本上是一系列项目。如果单击一个,其状态将更改。它添加到收藏夹并显示在收藏夹列表中(也是ListView)或从收藏夹中删除。

这是我的应用程序的主要功能,因此会有很多添加删除功能。更新后,这两个列表都很慢,有错误和闪烁。

我怎样才能让它更快/更顺畅?

我尝试在工作线程上运行所有添加/删除调用。我尝试过使用Taskasync函数(实际上使其更糟)。是否有适当的"这个场景的实现?(ListView ui线程和工作线程让它保持最新)是否有一篇文章可以教我良好的实践?

实现: 注意:Truck是另一个存储数据的类。 从数据类:

List<Truck> trucks = new List<Truck>();
public void addToFavorites(Truck truck)
{
    foreach(Truck t in trucks)
    {
        if(t == truck)
        {
            t.setFavorite(true);
        }
    }
}
public void removeFromFavorites(Truck truck)
{
    foreach (Truck t in trucks)
    {
        if (t == truck)
        {
            t.setFavorite(true);
        }
    }
}
public List<Truck> getTrucks()
{
    return trucks;
}
public List<Truck> getFavoriteTrucks()
{
    List<Truck> temp = new List<Truck>();
    foreach(Truck t in trucks)
    {
        if (t.isFavorite())
        {
            temp.Add(t);
        }
    }
    return temp;
}

从显示所有卡车的页面:

public partial class AllPage : ContentPage
{
    public AllPage(csharp.Data data)
    {
        //init
        InitializeComponent();
        this.data = data;
        //build list
        refreshAsync();
        ListView list = new ListView()
        {
            ItemTemplate = new DataTemplate(typeof(csharp.PlateCell)),
            ItemsSource = trucks,
            IsPullToRefreshEnabled = true,
        };
        //on select
        list.ItemSelected += (sender, e) => {
            if (e.SelectedItem == null) return; //row deselected, dont do anything
            var selection = e.SelectedItem as csharp.Truck;
            if (selection.isFavorite())
            {
                data.removeFromFavorites(selection);
                selection.setFavorite(false);
            }
            else { 
                data.addToFavorites(selection);
                selection.setFavorite(true);
            }
            ((ListView)sender).SelectedItem = null; // de-select the row
            refreshAsync();
        };
        list.RefreshCommand = new Command(() =>
        {
            //trucks = data.getFavoriteTrucks();
            refreshAsync();
            list.IsRefreshing = false;
        });
        //add the list to the page
        root.Children.Add(list);
    }//end constructor
    csharp.Data data;
    ObservableCollection<csharp.Truck> trucks = new ObservableCollection<csharp.Truck>();

    private async Task refreshAsync()
    {
        await Task.Run(() => refreshThread());
    }

    private void refreshThread()
    {
        List<csharp.Truck> all = data.getTrucks();
        trucks.Clear();
        foreach (csharp.Truck t in all)
        {
            trucks.Add(t);
        }
    }
}

2 个答案:

答案 0 :(得分:4)

我认为一个好的起点是告诉自己Virtualizing

您应避免在GUI线程以外的其他线程中更新可观察集合(查看this

还有一个好处是看看MVVM

据我所见,您将始终删除列表并重新填写,而不是仅传播更改。 - &GT;这应该是您的重点,以利用虚拟化

您也可以查看this。使用SmartCollection,您只会触发一次CollectionChanged事件,而不是您添加到列表中的每个项目

答案 1 :(得分:0)

您可能想查看this线程,谈论FastCell。我还没有尝试过他的图书馆,但我打算在Android上有一个非常不稳定的列表。

我听说在任何时候限制列表中的项目数量都会有所帮助,但它对我来说似乎没什么用。

此外,ListView现在允许您启用ListViewCachingStrategy. RecycleElement这应该有用,但听起来对你来说它目前无效,因为你正在更改ViewCell的内容。我碰到了同样的事情。启用后,iOS似乎会缓存您的ViewCell的初始布局,因此当您更改ViewCell的布局时,UI不会更新。我知道有一个错误报告,但不确定它的状态是什么。

除此之外,我会尽可能简单地PlateCellViewCell中的图片,标签和布局越多,情况就越糟糕。您也可以在AbsoluteLayout中使用ViewCell,如果操作正确,可以大大减少所需的布局计算次数。

我还不愿意做的最后一步是用本机代码编写你的ViewCell,我听说它比用Xamarin Forms写一个更高效。

让我们知道是否有什么事情可以帮助你!