【问题标题】:What steps can be taken to optimize a ListView可以采取哪些步骤来优化 ListView
【发布时间】:2016-08-19 11:25:22
【问题描述】:

我有一个ObservableCollection 绑定到一个ListView。这个列表基本上是一个项目的选择。如果单击一个,它的状态就会改变。它已添加到收藏夹并显示在收藏夹列表中(也是ListView),或者从收藏夹中删除。

这是我的应用程序的主要功能,因此会有很多添加-删除操作。这两个列表在更新时都很慢、有错误并且闪烁。

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

我已尝试在工作线程上运行所有添加/删除调用。我尝试过使用Taskasync 函数(实际上这让情况变得更糟)。这种场景是否有“正确”的实现方式?(ListView ui 线程和工作线程使其保持最新)是否有文章可以教我良好的做法?

实施: 注意:卡车是另一个存储数据的类。 来自数据类:

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);
        }
    }
}

【问题讨论】:

  • 您能否添加代码您如何实现一个它添加到收藏夹并显示在收藏夹列表(也是一个ListView)中或从收藏夹中删除。
  • 添加了存储所有内容的数据类以及显示此数据的 ListView 的实现。请注意,Data 类将来会从服务器获取其信息。当前,对于 Data 和 allPage,列表在大小和包含的对象方面始终相同,但情况并非总是如此。

标签: c# xamarin.forms


【解决方案1】:

我认为一个很好的起点是让自己了解Virtualizing

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

也可以看看MVVM

据我所知,您将始终删除您的列表并再次填写,而不是仅传播更改。 -> 这应该是您使用虚拟化的重点

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

【讨论】:

  • 添加了实现,现在将阅读您的链接。感谢您的回答!
  • 如前所述,每次刷新时周围可能会有或多或少的对象。在某些时候,肯定在进行拉动刷新时,我必须从我的数据类中获取更新的列表。此外,当我从 ObservableCollection 中的卡车对象更改字段时,它不会更新我的列表视图。我会浏览你的链接,我肯定会找到我的答案。
  • 如果一个项目在 observableCollection 中得到更新,它必须生成一个 PropertyChanged 事件,否则更改不会更新 UI。一个好的方法是让您的所有视图模型(在本例中为卡车)从实现 INotifyPropertyChanged 接口的 ViewModel 基类继承。您的属性的 Set 方法应该为此属性生成一个 PropertyChangedEvent
  • 会调查的。再次感谢。
【解决方案2】:

您可能想查看this 讨论 FastCell 的线程。我还没有尝试过他的库,但我正计划尝试,因为我还有一个在 Android 上非常不稳定的列表。

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

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

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

我还不愿意做的最后一步是用本机代码编写您的ViewCell,我听说这比用 Xamarin Forms 编写的性能要好得多。

如果有什么对你有用的,请告诉我们!

【讨论】:

  • 按照 Markus 的建议实现 INotifyPropertChanged 接口创造了奇迹。当我拉动以刷新它的混乱时,但我愿意接受,它只是一秒钟的混乱。使列表视图更小听起来是个好主意,或者以其他方式减少项目的数量,但是您稍后会遇到问题。并非每个设备都具有相同的屏幕尺寸,除非所有列表视图项都按比例缩放,否则您最终会再次遇到相同的问题。至于视单元,您可能是对的。将 hasUnevenRows 设置为 false 对性能也有很大帮助。
  • @wasted 感谢您回复对您有用的内容。我已经实现了,但我相信它会帮助其他人。如果你发现更多的调整让我知道!再次感谢。
  • Rohit 上面评论过,我发现,在他发布的文章中,实例化后设置一个listviews 的可见性或颜色会降低性能。检查上面,他发布了一个链接,其中包含一些可能对您有用的更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-21
  • 2015-07-22
相关资源
最近更新 更多