ListView 优化之 ViewHolder 复用机制
文章内容摘取自-
深入了解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 复用机制相关推荐
- ListView优化机制及滑动时数据时出现的数据错乱重复问题
ListView优化机制及滑动时数据时出现的数据错乱重复问题 转载于:https://www.cnblogs.com/zhujiabin/p/5596998.html
- reclyview 复用机制_RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)...
转载于csdn苦逼程序员的笔记博客 对于使用ViewHolder引起的图片错乱问题,相信大部分人都有遇到过,我也一样,对于解决方法也有所了解,但一直都是知其然不知其所以然. 所以,这次直接把ViewH ...
- Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑
RecyclerView中EditText和ImageView的ViewHolder复用坑 RecyclerView作为ListView的升级版,目前来讲讲开发过程遇到的坑. RecyclerView ...
- 一篇文章搞定《RecyclerView缓存复用机制》
一篇文章搞定<RecyclerView缓存复用机制> 前言 零.为什么要缓存 一.RecyclerView如何构建我们的列表视图 二.缓存过程 三.缓存结构 1.mChangedScrap ...
- 【提升栈】ListView优化
前言 ListView优化一直是一个老生常谈的问题.无论是面试还是寻常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看怎样最大化的优化ListView的性能. 1.在adapter中 ...
- 深入理解移动开发的模板复用机制
为什么80%的码农都做不了架构师?>>> 模板复用机制是android,ios等移动开发技术中类似listview,gridview,slideview等等之类组件常用的技术, ...
- ListView优化的代码
第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 ...
- ListView和GridView的缓存机制及measure过程
目录 前言 1.View的Transient状态 2.RecycleBin 3.obtainView 4.getView的调用 5.GridView的onMeasure 6.ListView的onMe ...
- facebook新闻页ListView优化
转自 http://blog.aaapei.com/article/2015/02/facebookxin-wen-ye-listviewyou-hua 引言 原文链接:https://code.fa ...
- RecyclerView中ViewHolder重用机制理解(解决图片错乱和闪烁问题)
对于使用ViewHolder引起的图片错乱问题,相信大部分人都有遇到过,我也一样,对于解决方法也有所了解,但一直都是知其然不知其所以然. 所以,这次直接把ViewHolder的工作原理,通过简单的de ...
最新文章
- 2016年深圳市宝安区小一学位申请流程及时间安排
- What Are You Talking About HDU1075
- Web前端期末大作业--汽车主题网页设计002(HTML+CSS+JavaScript+)实现
- zynq开发系列1:vivado和sdk联合使用串口打印helloworld
- 【现代通信原理笔记】6 信源编码
- 解决一例:“无法删除文件,无法读源文件或磁盘”
- Texstudio安装后闪退|重装系统Windows10|texstudio2022
- jQuery stop()用法
- 社群空间站一键发布微信群精品优质社群的搜索和发布平台源码
- Python画玫瑰花源代码
- 将dwg文件转为shp文件
- listen监听队列刨析
- 如何设计安全可靠的开放接口---对请求参加密保护
- 服务器:SATA、PATA及IDE的比较
- JAAS基于用户身份的验证和授权
- 【免费压缩图片的在线地址】
- C51 ADC0804LCN 应用
- 《电商法》将至:朋友圈的微商们该何去何从?
- AE插件GifGun一键创建输出gif动图
- 如何解决服务之间的通信问题?
热门文章
- php李炎辉,李炎恢PHP视频教程第一季资源分享
- 转专业到华侨大学计算机学院,关于2020年转专业工作安排的通知
- 攻防世界 WEB bilibili
- 最新影视小程序源码去授权版免费下载
- Visual Studio2019出现“ 激活远程语言服务器 c#/Visual Basic 语言服务器客户端出错”请运行devenv/log...…“的解决办法
- 常用触摸屏485通讯引脚及下载口
- win7计算机高级还原,最好用的win7一键恢复64位方法
- 苹果13可以用无线充电宝吗?苹果专用无线充电宝推荐
- 【素史】曼怛罗(70)
- 使用 LwIP TCP/IP 栈,在 STM32Cube 上开发应用