热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

什么是回收ListView中这种看不见的性能食物细胞?

如何解决《什么是回收ListView中这种看不见的性能食物细胞?》经验,如何解决这个问题?

所以我的Xamarin.Forms应用程序(在Android上)使用了一个性能问题ListView.原因是,因为我在ListView中使用了一个非常复杂的自定义控件ItemTemplate.

为了提高性能,我在自定义控件中实现了许多缓存功能,并将ListView设置CachingStrategyRecycleElement.

表现并没有好转.所以我试图找出原因是什么.

我终于发现了一些非常奇怪的bug并将其隔离在一个新的空应用中.代码如下:

MainPage.xaml中


    
        
    

    
        
            
                
                    
                
            
        
    

TestControl.cs

public class TestControl : Grid
{
    static int id = 0;
    int myid;

    public static readonly BindableProperty FooProperty = BindableProperty.Create("Foo", typeof(string), typeof(TestControl), "", BindingMode.OneWay, null, (bindable, oldValue, newValue) =>
    {
        int sourceId = ((TestControl)bindable).myid;
        Debug.WriteLine(String.Format("Refreshed Binding on TestControl with ID {0}. Old value: '{1}', New value: '{2}'", sourceId, oldValue, newValue));
    });

    public string Foo
    {
        get { return (string)GetValue(FooProperty); }
        set { SetValue(FooProperty, value); }
    }

    public TestControl()
    {
        this.myid = ++id;

        Label label = new Label
        {
            Margin = new Thickness(0, 15),
            FOntSize= Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
            Text = this.myid.ToString()
        };
        this.Children?.Add(label);
    }
}

MainViewModel.cs

public class MainViewModel
{
    public List Numbers { get; set; } = new List()
    {
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine",
        "ten",
        "eleven",
        "twelve",
        "thirteen",
        "fourteen",
        "fifteen",
        "sixteen",
        "seventeen",
        "eighteen",
        "nineteen",
        "twenty"
    };
}

注意CachingStrategy就是RetainElement.每个都TestControl获得一个唯一的升序ID,显示在UI中.让我们运行应用程序!

没有回收

禁用回收的屏幕截图

[0:] Refreshed Binding on TestControl with ID 1. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 1. Old value: '', New value: 'one'
[0:] Refreshed Binding on TestControl with ID 2. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 2. Old value: '', New value: 'two'
[0:] Refreshed Binding on TestControl with ID 3. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 3. Old value: '', New value: 'three'
[0:] Refreshed Binding on TestControl with ID 4. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 4. Old value: '', New value: 'four'
[0:] Refreshed Binding on TestControl with ID 5. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 5. Old value: '', New value: 'five'
[0:] Refreshed Binding on TestControl with ID 6. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 6. Old value: '', New value: 'six'
[0:] Refreshed Binding on TestControl with ID 7. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 7. Old value: '', New value: 'seven'
[0:] Refreshed Binding on TestControl with ID 8. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 8. Old value: '', New value: 'eight'
[0:] Refreshed Binding on TestControl with ID 9. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 9. Old value: '', New value: 'nine'
[0:] Refreshed Binding on TestControl with ID 10. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 10. Old value: '', New value: 'ten'
[0:] Refreshed Binding on TestControl with ID 11. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 11. Old value: '', New value: 'eleven'
[0:] Refreshed Binding on TestControl with ID 12. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 12. Old value: '', New value: 'twelve'

好吧,每个Binding由于某种原因被解雇两次.这不会发生在我的实际应用中,因此我并不在乎.我还比较了oldValue和newValue,如果它们是相同的则不执行任何操作,因此这种行为不会影响性能.

有趣的事情发生在我们设置CachingStrategyRecycleElement:

随着回收

启用回收的屏幕截图

[0:] Refreshed Binding on TestControl with ID 1. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 1. Old value: '', New value: 'one'
[0:] Refreshed Binding on TestControl with ID 2. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 2. Old value: '', New value: 'one'
[0:] Refreshed Binding on TestControl with ID 3. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 3. Old value: '', New value: 'two'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'one', New value: 'two'
[0:] Refreshed Binding on TestControl with ID 4. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 4. Old value: '', New value: 'three'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'two', New value: 'three'
[0:] Refreshed Binding on TestControl with ID 5. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 5. Old value: '', New value: 'four'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'three', New value: 'four'
[0:] Refreshed Binding on TestControl with ID 6. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 6. Old value: '', New value: 'five'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'four', New value: 'five'
[0:] Refreshed Binding on TestControl with ID 7. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 7. Old value: '', New value: 'six'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'five', New value: 'six'
[0:] Refreshed Binding on TestControl with ID 8. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 8. Old value: '', New value: 'seven'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'six', New value: 'seven'
[0:] Refreshed Binding on TestControl with ID 9. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 9. Old value: '', New value: 'eight'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'seven', New value: 'eight'
[0:] Refreshed Binding on TestControl with ID 10. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 10. Old value: '', New value: 'nine'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'eight', New value: 'nine'
[0:] Refreshed Binding on TestControl with ID 11. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 11. Old value: '', New value: 'ten'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'nine', New value: 'ten'
[0:] Refreshed Binding on TestControl with ID 12. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 12. Old value: '', New value: 'eleven'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'ten', New value: 'eleven'
[0:] Refreshed Binding on TestControl with ID 13. Old value: '', New value: ''
[0:] Refreshed Binding on TestControl with ID 13. Old value: '', New value: 'twelve'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'eleven', New value: 'twelve'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'twelve', New value: 'one'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'one', New value: 'two'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'two', New value: 'three'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'three', New value: 'four'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'four', New value: 'five'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'five', New value: 'six'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'six', New value: 'seven'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'seven', New value: 'eight'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'eight', New value: 'nine'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'nine', New value: 'ten'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'ten', New value: 'eleven'
[0:] Refreshed Binding on TestControl with ID 1. Old value: 'eleven', New value: 'twelve'

哎呀.单元格1是不可见的,但它的Binding更新了很多.我甚至没有触摸屏幕一次,因此不涉及滚动.

当我点击屏幕并向下滚动大约一个或两个像素时,ID 1的绑定会再次刷新15次.

请参阅此视频,向我滚动ListView:https:
//www.youtube.com/watch?v = EuWTGclz7uc

这是我真实应用程序中的绝对性能杀手,这TestControl是一个非常复杂的控件.

有趣的是,在我的真实应用程序中,它是ID 2而不是ID 1,这是错误的.我假设它总是第二个单元格,所以如果ID为2,我最终会立即返回.这使得ListView性能更加流畅.

现在我已经能够用2以外的ID重现这个问题,我害怕我自己的解决方案.

因此我的问题是:这个看不见的单元是什么,为什么它会得到如此多的绑定更新以及如何绕过性能问题?

我测试了Xamarin.Forms版本2.3.4.247,2.3.4.270和2.4.0.269-pre2 on

三星Galaxy S5 mini(Android 6.0)

三星Galaxy Tab S2(Android 7.0)

我没有在iOS设备上测试.


推荐阅读
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 本文介绍了如何将CIM_DateTime解析为.Net DateTime,并分享了解析过程中可能遇到的问题和解决方法。通过使用DateTime.ParseExact方法和适当的格式字符串,可以成功解析CIM_DateTime字符串。同时还提供了关于WMI和字符串格式的相关信息。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
author-avatar
长风剑客2502852893
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有