开发者社区> lauren_liuling> 正文

【译文】高性能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死掉,我们一定得避免这种情况发生。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
带你读《数据自治》前言第一章绪论1.5小结
带你读《数据自治》前言第一章绪论1.5小结
41 0
带你读《云原生应用开发 Operator原理与实践》第一章引言1.3本章小结
带你读《云原生应用开发 Operator原理与实践》第一章引言1.3本章小结
70 0
分享一些常用的开源博客社区网站
分享一些常用的开源博客社区网站
161 0
关于一些主流博客框架的介绍
关于一些主流博客框架的介绍
298 0
内存数据库技术简述
随着内存价格的持续降低和内存容量的不断扩大,在某些场景之内,以内存作为存放数据的主力方式成为可能。相对比于硬盘数据库、闪存数据库,内存数据库的发展经历了哪些阶段?我们应该如何重新审视内存数据库?本文将进行探讨。
4896 0
Alluxio使用——开篇
一.Alluxio概述 Alluxio(前身Tachyon)是世界上第一个以内存为中心的虚拟的分布式存储系统。它统一了数据访问的方式,为上层计算框架和底层存储系统构建了桥梁。 Alluxio项目源自加州大学伯克利分校AMPLab,作为伯克利数据分析堆栈(BDAS)的数据访问层。
7996 0
Cassandra技术介绍之开篇
cassandra的技术浅谈
2157 0
设计模式概念与简介(原创)
设计模式 什么是设计模式? 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。
974 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载