文章内容摘取自-
深入了解ListView工作原理(一) – 之viewHolder优化篇
ListView中convertView和ViewHolder的复用机制工作原理

ViewHolder 复用机制

在使用 ListView 过程中适配器 Adapter 中的 getView() 方法中已经通过 convertView 复用机制(RecycleBin 回收再利用) 进行了优化。

但我们发现代码中仍然存在可以改进的地方,观察如下代码

public View getView(int position, View convertView, ViewGroup parent) {  Fruit fruit = getItem(position);  View view;  if (convertView == null) {  view = LayoutInflater.from(getContext()).inflate(resourceId, null);  } else {  view = convertView;  }  ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);  TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);  fruitImage.setImageResource(fruit.getImageId());  fruitName.setText(fruit.getName());  return view;
}  

我们发现虽然 convertView 是实现了复用,但是每次 getView() 时,都要对每个子 View 中包含的控件进行实例化(findViewById)操作,这也是一个耗时的操作,这里就使用到了 ViewHolder 这个类来进行优化操作。

public View getView(int position, View convertView, ViewGroup parent) {System.out.println("getView " + position + " " + convertView);ViewHolder holder = null;if (convertView == null) {convertView = mInflater.inflate(R.layout.lv_item, null);holder = new ViewHolder();holder.textView = (TextView)convertView.findViewById(R.id.tv_text);convertView.setTag(holder);} else {holder = (ViewHolder)convertView.getTag();}holder.textView.setText(mData.get(position));return convertView;}
}public static class ViewHolder {public TextView textView;}

如上代码所述,我们把每个子 View 中包含的控件(需要实例化的)都放到 ViewHolder 的静态内部类中。当第一次创建 convertView 对象时,把 ViewHolder 中的控件都进行实例化,然后用 convertView 的 setTag() 方法将 ViewHolder 设置到 Tag 中,以便系统第二次调用 getView() 方法时子 View 中需要的控件可以直接通过 convertView.getTag() 方法取出 ViewHolder 容器对象,然后直接调用需要的控件即可。

ListView 中的 convertView 和 ViewHolder 协同

ListView 里面的每一个 item 都是通过 adapter 来得到的,然后根据 listView 的高度和 item 的高度来循环加载显示在 listView 上,因此首次加载就决定了能够显示出来的 item 的个数,并且首次走进的都是 getView() 方法里 convertView==null 的时候,也就是说,此时加载了几个 item(包括只显示一部分的),就创建了几个 ViewHolder 对象,ViewHolder 里的控件来指向对应的 convertView 里的控件。

图中显示了 ListView 显示出的6个 item,和对应生成的6个 ViewHolder 对象。并且在 ListView 工作过程中一直指向它们各自的 item。注意此时,RecycleBin 里还么有任何可以拿来复用的 convertView。若此时,ListView 向上滑动一部分,使得 item 1 一部分滚出 ListView 的 顶部,并且 item 7 也进入一部分,因为此时 RecycleBin 里没有任何可以复用的 convertView(废弃缓存里没有 View),所以,程序急促进入 convertView == null,ViewHolder 7也被创建,指向 item 7。如果此时继续滑动 item 1,使得页面刚好显示的是 item2-7, 将不会再生成新的 ViewHolder。此时滚出去的 item 1对应的 View 将被放入 RecycleBin 里面做备用的 convertView 1,如果继续往上滑动,item 8即将进入 ListView,此时 ListView 的 adapter 在 RecycleBin 里找到了可以复用的 convertView 1,而且因为之前用了 setTag 的方式,因此可以用 getTag 迅速获得 ViewHolder 1,并且 ViewHolder 1是始终指向 convertView 1,因此直接可以根据 position 来设置对应的图片,文本然后 return 此更新后的 View 给 ListView 来显示 item 8。

做 ViewHolder 来优化 ListView 时,需要用 static 来修饰 ViewHolder 类?

我们把 ViewHolder 类设置成 static 静态类,是想让整个内存中之需要一份 ViewHolder 对象,来优化 ListView。

但是通过实验发现

//把ViewHolder变为static之后,getView()里加上如下代码:
viewHolder = new ViewHolder();
AppLog.i("viewHolder" + i +" = " + viewHolder );
i++;20.548 12491-12491/?  [getView()] - viewHolder1 = $ViewHolder@e6a668d
20.627 12491-12491/?  [getView()] - viewHolder2 = $ViewHolder@22e2da45
20.629 12491-12491/?  [getView()] - viewHolder3 = $ViewHolder@355bd5c1
20.632 12491-12491/?  [getView()] - viewHolder4 = $ViewHolder@210f0cfd
20.635 12491-12491/?  [getView()] - viewHolder5 = $ViewHolder@3c47bf9
20.637 12491-12491/?  [getView()] - viewHolder6 = $ViewHolder@35c7deb5
20.640 12491-12491/?  [getView()] - viewHolder7 = $ViewHolder@e64b131
20.642 12491-12491/?  [getView()] - viewHolder8 = $ViewHolder@34222f6d
20.644 12491-12491/?  [getView()] - viewHolder9 = $ViewHolder@34bf5569
20.647 12491-12491/?  [getView()] - viewHolder10 = $ViewHolder@20eedf25
20.650 12491-12491/?  [getView()] - viewHolder11 = $ViewHolder@27d348a1
20.653 12491-12491/?  [getView()] - viewHolder12 = $ViewHolder@2e3acddd
20.656 12491-12491/?  [getView()] - viewHolder13 = $ViewHolder@3290cc9e
40.937 12491-12491/: [MainActivity$1:48 onScrollStateChanged()] - scroll
44.879 12491-12491/: [MainActivity$1:52 onScrollStateChanged()] - fling
44.994 12491-12491/: [MainActivity$1:44 onScrollStateChanged()] - idle

静态内部类的实例地址都是不一样的,所以并没有优化 ViewHolder 的个数。然而实际情况是因为 convertView 的复用机制,convertView 不会太多,一般情况下=ListView 显示的 item 个数 + 1*viewTypeCount。所以 ViewHolder 的个数也不会太多。所以没有优化的意义。

文章只是作为个人记录学习使用,如有不妥之处请指正,谢谢。

文章内容摘取自-
深入了解ListView工作原理(一) – 之viewHolder优化篇
ListView中convertView和ViewHolder的复用机制工作原理

ListView 优化之 ViewHolder 复用机制相关推荐

  1. ListView优化机制及滑动时数据时出现的数据错乱重复问题

    ListView优化机制及滑动时数据时出现的数据错乱重复问题 转载于:https://www.cnblogs.com/zhujiabin/p/5596998.html

  2. reclyview 复用机制_RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)...

    转载于csdn苦逼程序员的笔记博客 对于使用ViewHolder引起的图片错乱问题,相信大部分人都有遇到过,我也一样,对于解决方法也有所了解,但一直都是知其然不知其所以然. 所以,这次直接把ViewH ...

  3. Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑

    RecyclerView中EditText和ImageView的ViewHolder复用坑 RecyclerView作为ListView的升级版,目前来讲讲开发过程遇到的坑. RecyclerView ...

  4. 一篇文章搞定《RecyclerView缓存复用机制》

    一篇文章搞定<RecyclerView缓存复用机制> 前言 零.为什么要缓存 一.RecyclerView如何构建我们的列表视图 二.缓存过程 三.缓存结构 1.mChangedScrap ...

  5. 【提升栈】ListView优化

    前言 ListView优化一直是一个老生常谈的问题.无论是面试还是寻常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看怎样最大化的优化ListView的性能. 1.在adapter中 ...

  6. 深入理解移动开发的模板复用机制

    为什么80%的码农都做不了架构师?>>>    模板复用机制是android,ios等移动开发技术中类似listview,gridview,slideview等等之类组件常用的技术, ...

  7. ListView优化的代码

    第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 ...

  8. ListView和GridView的缓存机制及measure过程

    目录 前言 1.View的Transient状态 2.RecycleBin 3.obtainView 4.getView的调用 5.GridView的onMeasure 6.ListView的onMe ...

  9. facebook新闻页ListView优化

    转自 http://blog.aaapei.com/article/2015/02/facebookxin-wen-ye-listviewyou-hua 引言 原文链接:https://code.fa ...

  10. RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)

    对于使用ViewHolder引起的图片错乱问题,相信大部分人都有遇到过,我也一样,对于解决方法也有所了解,但一直都是知其然不知其所以然. 所以,这次直接把ViewHolder的工作原理,通过简单的de ...

最新文章

  1. 2016年深圳市宝安区小一学位申请流程及时间安排
  2. What Are You Talking About HDU1075
  3. Web前端期末大作业--汽车主题网页设计002(HTML+CSS+JavaScript+)实现
  4. zynq开发系列1:vivado和sdk联合使用串口打印helloworld
  5. 【现代通信原理笔记】6 信源编码
  6. 解决一例:“无法删除文件,无法读源文件或磁盘”
  7. Texstudio安装后闪退|重装系统Windows10|texstudio2022
  8. jQuery stop()用法
  9. 社群空间站一键发布微信群精品优质社群的搜索和发布平台源码
  10. Python画玫瑰花源代码
  11. 将dwg文件转为shp文件
  12. listen监听队列刨析
  13. 如何设计安全可靠的开放接口---对请求参加密保护
  14. 服务器:SATA、PATA及IDE的比较
  15. JAAS基于用户身份的验证和授权
  16. 【免费压缩图片的在线地址】
  17. C51 ADC0804LCN 应用
  18. 《电商法》将至:朋友圈的微商们该何去何从?
  19. AE插件GifGun一键创建输出gif动图
  20. 如何解决服务之间的通信问题?

热门文章

  1. php李炎辉,李炎恢PHP视频教程第一季资源分享
  2. 转专业到华侨大学计算机学院,关于2020年转专业工作安排的通知
  3. 攻防世界 WEB bilibili
  4. 最新影视小程序源码去授权版免费下载
  5. Visual Studio2019出现“ 激活远程语言服务器 c#/Visual Basic 语言服务器客户端出错”请运行devenv/log...…“的解决办法
  6. 常用触摸屏485通讯引脚及下载口
  7. win7计算机高级还原,最好用的win7一键恢复64位方法
  8. 苹果13可以用无线充电宝吗?苹果专用无线充电宝推荐
  9. 【素史】曼怛罗(70)
  10. 使用 LwIP TCP/IP 栈,在 STM32Cube 上开发应用