1. 首先,虽然大家都知道,还是提一下,利用好 convertView 来重用 View,切忌每次 getView() 都新建。ListView 的核心原理就是重用 View。ListView 中有一个回收器,Item 滑出界面的时候 View 会回收到这里,需要显示新的 Item 的时候,就尽量重用回收器里面的 View。
  2. 利用好 View Type,例如你的 ListView 中有几个类型的 Item,需要给每个类型创建不同的 View,这样有利于 ListView 的回收,当然类型不能太多;
  3. 尽量让 ItemView 的 Layout 层次结构简单,这是所有 Layout 都必须遵循的;
  4. 善用自定义 View,自定义 View 可以有效的减小 Layout 的层级,而且对绘制过程可以很好的控制;
  5. 尽量能保证 Adapter 的 hasStableIds() 返回 true,这样在 notifyDataSetChanged() 的时候,如果 id 不变,ListView 将不会重新绘制这个 View,达到优化的目的;
  6. 每个 Item 不能太高,特别是不要超过屏幕的高度,可以参考 Facebook 的优化方法,把特别复杂的 Item 分解成若干小的 Item,特别推荐看一下这个文章:https://code.facebook.com/posts/879498888759525/fast-rendering-news-feed-on-android/
  7. 为了保证 ListView 滑动的流畅性,getView() 中要做尽量少的事情,不要有耗时的操作。特别是滑动的时候不要加载图片,停下来再加载,这个库可以帮助你 Glide:https://github.com/bumptech/glide
  8. 使用 RecycleView 代替。 ListView 每次更新数据都要 notifyDataSetChanged(),有些太暴力了。RecycleView 在性能和可定制性上都有很大的改善,推荐使用。

 
比如你的Item中有三个按钮,你要为三个按钮分别定义点击事件,如何定义?

也许你会在getView中这样做

  1.  1 button1.setOnclickListener(new View.OnClickListener() {
     2     @override
     3     public void onClick(View v) {
     4         //balabalabala...
     5     }
     6 });
     7 button2.setOnclickListener(new View.OnClickListener() {
     8     @override
     9     public void onClick(View v) {
    10         //balabalabala...
    11     }
    12 });
    13 button3.setOnclickListener(new View.OnClickListener() {
    14     @override
    15     public void onClick(View v) {
    16         //balabalabala...
    17     }
    18 });

如果你每屏显示7个Item,你一共创建了21个listener对象在内存中,如果View回收不畅,会更多,这样,在滚动的时候频繁GC 就会导致卡顿(这里描述有误,请看7月25日更新)

如果你在Adapter初始化的时候创建一个Listener

public MyAdapter () {myListener = new View.OnClickListener() {@overridepublic void onClick(View v) {v.getTag()v.getId()//balabalabala...
        }});
}

通过传入的View v这个参数判断是哪一个button被点击,这样,无论View如何创建,你只创建了1个Listener对象

这只是一个小细节,优化的方式要综合使用,才会事半功倍

------------------7月24日更-----------------

v.getTag() 这个tag本不是用来存数据的,通俗点讲它和view 的Id是同一个东西,只不过tag的类型是Object。实际上在tag中存储数据是不符合规范的方式

但其实View类有两种tag,
setTag(Object tag) 方法将tag保存在一个成员变量中,findViewWithTag正是遍历此tag

setTag(int key, Object tag) 方法是最终是调用View类中的setKeyedTag(int key, Object tag)
这是一个私有方法
他是用 SparseArray 实现的,我们可以把需要的东西存到这里面(其实观察源码可以发现,系统很多时候都是这样做的)

这里要注意一点,参数key必须是唯一的,那么我们可以这样做
那么需要先在res/values/strings.xml中添加

  1. <resources>
    <item type="id" name="tag_first"></item>
    <item type="id" name="tag_second"></item>
    </resources>

  2. 使用的时候写成
  3. view.setTag(R.id.tag_first, obj1);
    view.setTag(R.id.tag_second, obj2);

-------------------------关于如何绑定数据的问题-----------------

有人问,如果这样写,所有button只能通过id区分逻辑,无法传入每个item的数据

我们可以将数据通过view 的tag带进来

1 public View getView(.....) {
2 ....
3 v.setTag(key, getItem(position));
4 ....
5 }

然后在listener中通过v.getTag()将数据取出
-----------------------7月25日update-------------------
这里我有一个失误
如果listener里面的逻辑与当前的item有关,那么其实并不只是创建了21个listener对象

 1 public void getView (View convertView ,final int position ....) {
 2     if (convertView == null) {
 3         View v = LayoutInflater.from(mContext).inflate(...);
 4         v.setOnclickListener(new View.OnClickListener () {
 5             @override
 6             public void onClick(View v) {
 7                 getItem(position);
 8             }
 9         });
10     } else {
11
12     }
13 }

你看下,如果绑定数据在convertView为空的情况下确实只创建了有限个listener,
但是在这种情况下绑定上的数据只有View创建时的7个,之后不为空的情况下没有更换listener导致重用的view数据是新的,listener里面的position依然是过去创建view时的7个之一,不会变化(注意参数上的final)
若在else里面再重新setListener,view是有重用,listener被换成新的,并与新的position绑定,老的listener就会变成一个废对象,等待gc回收,随着list滚动,越来越多
关键是我们的业务与position这个参数有关


1.重用 convertView 
用以避免重复创建 View,重复创建 View 代价较大,而且如果重用 view 不改变宽高,重用View可以减少重新分配缓存造成的内存频繁分配/回收;

2. 避免在 getView 中有 重复调用的 findViewById
findViewById 的实现是遍历,如果你定义的 View 越复杂代价越大。
Google 推荐的做法是用 ViewHolder,然后保存在 view 的 tag 中。现在 RecyclerView 也是强制使用 ViewHolder 了。

3. 设置 View (如 TextView#setText )之前先对比数据是否有改变
一般来说,【比较两个数据的代价】远小于【 View 的重绘的代价】

4. 避免在 getView 函数中直接加载 Image 或做其他比较耗时的操作
加载本地 Image 需要载入内存以及解析 Bitmap ,都是比较耗时的操作。
用户快速滑动列表时,会大量调用 getView ,而 getView 是在主线程中被调用的。如果你在 getView 函数中直接加载 Image 或做其他耗时操作,就会造成滑动比较卡。加载 ImageView 的解决方案就是开一个线程去把做这事。有很多第三库可以做这事。

5. ListView 中元素避免半透明
半透明绘制需要大量乘法计算,在滑动时不停重绘会造成大量的计算,在比较差的机子上会比较卡。在设计上能不半透明就不不半透明。实在要弄的话我个人是用个比较偷懒的方法,是在滑动的时候把半透明设置成不透明,滑动完再重新设置成半透明。

6. 尽量开启硬件加速
硬件加速提升巨大,避免使用一些不支持的函数导致含泪关闭某个地方的硬件加速。
当然这一条不只是对 ListView。

7.用 ListView 威力加强版 -- RecyclerView
更多的新武将,更多的姿势,更规范的使用,更好用的动画,更加强大的变化

 
转载自知乎(http://www.zhihu.com/question/19703384)

Listview性能优化相关推荐

  1. ym——Android之ListView性能优化

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! Android之ListView性能优化 假设有看过我写过的15k面试题的朋友们一定知 ...

  2. Android ListView性能优化实例讲解

    前言: 对于ListView,大家绝对都不会陌生,只要是做过Android开发的人,哪有不用ListView的呢? 只要是用过ListView的人,哪有不关心对它性能优化的呢? 关于如何对ListVi ...

  3. Android Listview 性能优化

    首先我一般使用的适配器是BaseAdapter,其中有两个方法最主要,分别是: getCount,getView, 在对Listview 进行优化的时候,首先使用 convertview 和viewH ...

  4. (翻译) Android ListView 性能优化指南

    本文翻译了Lucas Rocha的Performance Tips for Android's ListView.这是一篇关于介绍如何提升ListView性能的文章,非常的优秀.使得我拜读之后,忍不住 ...

  5. [Android]ListView性能优化之视图缓存

    前言 ListView是Android中最常用的控件,通过适配器来进行数据适配然后显示出来,而其性能是个很值得研究的话题.本文与你一起探讨Google I/O提供的优化Adapter方案,欢迎大家交流 ...

  6. Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

    ListView 是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很 ...

  7. Android性能优化之提高ListView性能的技巧

    ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能. 1.在adapter中的ge ...

  8. Android 性能优化lt;九 RecyclerView替代Listview用法

    Android 性能优化 (一)APK高效瘦身 http://blog.csdn.net/whb20081815/article/details/70140063 Android 性能优化 (二)数据 ...

  9. Android开发——布局性能优化的一些技巧(一)

    0. 前言 上一篇我们分析了为什么LinearLayout会比RelativeLayout性能更高,意义在于分析了这两种布局的实现源码,算是对一个小结论的证明过程,但是对布局性能的优化效果,对这两种布 ...

最新文章

  1. PowerDesigner对列增加注释
  2. CUDA out of memory in pytorch
  3. a卡显存检测软件_科普小课堂,A卡玩家如何轻松超频?
  4. Jenkins配置基于角色的项目权限管理--转
  5. 聊聊ribbon的超时时间设置
  6. 2020年周记(2/50)
  7. hdfs为什么要用block以及block大小的设置
  8. html 手机复制到剪贴板,移动端和pc端的复制到剪贴板功能
  9. 《linux设备驱动开发详解》笔记——14 linux网络设备驱动
  10. linux下执行efi文件,在Linux下创建EFI BIOS Grub加载分区
  11. ubuntu 系统获取和阅读 linux 源码
  12. 二部图 欧拉图 哈密顿图 平面图 判定条件
  13. Office Tool Plus 安装2019版Office及Visio
  14. 地铁工程安全生产预警系统价格
  15. python遍历文件夹以及排序问题
  16. Apriori算法通俗讲解
  17. Oracle查询列重命名问题
  18. MapGuide源码分析----MapGuide Web扩展源码分析
  19. iOS应用的启动流程和优化详解
  20. opencv遍历像素的方式

热门文章

  1. Oceanus:美团HTTP流量定制化路由的实践
  2. ie8下jquery改变PNG的opacity出现黑边,ie6下png透明解决办法
  3. mongodb的增、删、改、插的一个实例
  4. [转]Supporting OData Query Options in ASP.NET Web API 2
  5. Jquery操作Cookie,保存商品ID值至本地文件中
  6. webzip下载整个网站工具-WebZip
  7. win7 64位系统oracle客户端访问远程数据库
  8. C++生成随机数:X2(卡方)分布(X2 distribution)
  9. java时间戳求时间差_时间戳换算后,截取时间相差8小时的问题
  10. c++ 写x64汇编 5参数_Vs配置汇编开发环境,智能提示、代码颜色应有尽有~来打我呀...