【译文】高性能ListViews

简介:

原文链接 : Performance ListViews
原文作者 : Brandon
译文出自 : 开发技术前线 www.devtf.cn。未经允许,不得转载!
译者 : liuling07
校对者: desmond1121
状态 : 完成

译文连接:高性能ListViews

列 表展示功能几乎在所有app中都会被用到,使用列表可以很方便的展示一些列表项,比如菜谱、联系人,或者任意类型的类别。所以Android有一个内置的 方式来展示此类型的数据,也是在情理之中的。RecyclerView是一种最新的展示列表数据的方式,它非常高效,因为它重用视图而不是每一行出现在屏 幕上都重新创建。在RecyclerView出现之前,我们可以使用ListView,即使到了现在,ListView也是广泛的被开发者所使用。虽然 ListView也是可以回收视图的,但它也一直都是Android中最容易被错误使用的一个控件。我们知道在此之前这个话题已经被写过无数遍了,但是今 天我还是要在博客中提出来,因为我们仍然发现很多app在错误的使用它们。

关于ListView中ArrayAdapter的用法,标准的新手写法是这样子的:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
 
    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.view_test_row, parent, false);
 
    TextView testName = (TextView)rowView.findViewById(R.id.text_view_test_name);
    TextView testDesc = (TextView)rowView.findViewById(R.id.text_view_test_desc);
 
    //modify TextViews, in some arbitrary way
 
    return rowView;
}

当所有列表项都能够一次性在一屏中显示的时候,这种写法并没有什么问题,但这样你就创建了一个基本视图,并完全避免了ArrayAdapter的麻 烦了吗?当ListView需要显示一个很大的列表集,而且列表子项是一个非常复杂的视图的时候,上面的方式会消耗大量的性能。当用户滑动屏幕的时候,每 个视图都会被inflate并且调用findViewById()方法。当findViewById()方法被调用的时候,会遍历整个视图层级,直到找到 正确的Id。每个子视图都要执行上述过程!并且用户滑动的越快,卡顿现象愈加明显。为了解决这个问题,我们可以使用一个静态类来绑定还没被使用的 convertView。

static class ViewHolder(){
 
        TextView testName;
        TextView testDesc;
 
}
 
@Override
 public View getView(int position, View convertView, ViewGroup parent) {
 
    View rowView = convertView;  //reference to one of the previous Views in the list that we can reuse.
 
    if(convertView == null) {
 
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(R.layout.view_test_row, parent, false);
 
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.testName = (TextView) rowView.findViewById(R.id.text_view_test_name);
        viewHolder.testDesc = (TextView) rowView.findViewById(R.id.text_view_test_desc);
 
        rowView.setTag(viewHolder);
    }
 
    ViewHolder holder = (ViewHolder) rowView.getTag();
 
    //in real code these strings should be in res
    holder.testName.setText("Test"+position);
    holder.testDesc.setText("This is number "+position);
 
    return rowView;
}

那convertView又是什么呢?它可以让ListView跳过一些显示一行内容所需要的设置。如果某一行的视图不在屏幕中显示,我们可以重复 使用这个视图来显示一个新行。当ListView刚开始显示的时候,一切都是正常的。既然没有视图可以被用来复用,convertView为空。视图也像 前面版本一样被inflate,但是TextViews会被找到且它的引用被保存在一个ViewHolder中。然后我们可以调用setTag()方法将 ViewHolder存储在视图中。正如修订过后的getView()方法中后半段代码所示,我们可以在视图中存储后面我们需要用到的数据。

我们所做的更改可能看起来并没有太大的效果,但是随着布局越来越复杂并且数量也越来越多,效果将变得越来越明显。作为开发者,我最不想做的事就是开 发一个用户体验很差的app。所以请记住,仅仅一个低水平的ListView都有可能让一个app死掉,我们一定得避免这种情况发生。

相关文章
|
存储 SQL 运维
涨姿势 | 一文读懂备受大厂青睐的ClickHouse高性能列存核心原理
本文尝试解读ClickHouse存储层的设计与实现,剖析它的性能奥妙
3668 0
涨姿势 | 一文读懂备受大厂青睐的ClickHouse高性能列存核心原理
|
8月前
|
存储 缓存 算法
【C 言专栏】C 语言实现算法的高效性
【5月更文挑战第6天】本文探讨了C语言在实现高效算法上的优势,包括其高效性、灵活性、可移植性和底层访问能力。关键点包括选择合适的数据结构(如数组、链表、树和图)、应用优化策略(如减少计算、空间换时间、分治和动态规划),以及内存管理和代码优化技巧。通过实际案例(如排序和图遍历算法),阐述了如何利用C语言实现算法高效性,并强调在实践中不断探索和优化以提升算法效率。C语言在计算机科学中的重要地位使其成为实现高效算法的首选工具。
133 0
【C 言专栏】C 语言实现算法的高效性
|
8月前
|
5G 网络架构
带你读《5G 系统技术原理与实现》精品文章合集
带你读《5G 系统技术原理与实现》精品文章合集
|
存储 Linux 测试技术
2023年C/C++高性能技术知识大整理(进阶到大神级别)
2023年C/C++高性能技术知识大整理(进阶到大神级别)
|
人工智能 运维 5G
带你读《5G 系统技术原理与实现》——前言
带你读《5G 系统技术原理与实现》——前言
|
传感器 前端开发 安全
【宝典】开发人员常见英语术语,掌握后,效率提升N倍(持续更新...)
【宝典】开发人员常见英语术语,掌握后,效率提升N倍(持续更新...)
183 0
|
运维 NoSQL 大数据
Cassandra技术介绍之开篇
cassandra的技术浅谈
2364 0
|
关系型数据库 PolarDB 分布式数据库
读懂POLARDB不能错过的18篇深度文章! | 开发者必读(086期)
最炫的技术新知、最热门的大咖公开课、最有趣的开发者活动、最实用的工具干货,就在《开发者必读》!
454 0
|
IDE 开发工具 API
用中文编程-专栏初衷回顾
在中文编程知乎专栏创立一周年之际, 对专栏初衷作回顾与修订. Revised goals for the "Programming in Chinese" column after one year.
976 0
|
IDE 编译器 API
中文编程专栏介绍, 初衷和希冀
中文编程的各个方面: 1. 以中文命名标识符 2. 汉化现有库/框架的接口(API) 3. 将现有编程语言进行汉化 4. 改进现有的, 以及创立新的中文编程语言及对应的开发集成环境
847 0