开发Android程序时;并且你想要一个 ArrayAdapter 你可以简单地拥有一个类(大多数情况下使用 ViewHolder 后缀)或直接膨胀你的 convertView 并找到你的按身份查看
那么使用ViewHolder有什么好处?
这两个例子都是:
if(convertView==null)
{
convertView = ((Activity)_context).getLayoutInflater().inflate(R.layout.row_phrase, null);
}
((TextView)convertView.findViewById(R.id.txtPhrase)).setText("Phrase 01");
或者:
static class ViewHolder {
ImageView leftIcon;
TextView upperLabel;
TextView lowerLabel;
}
最后在getView:
中ViewHolder holder = null;
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.row_layout,
null, false);
holder = new ViewHolder();
holder.leftIcon = (ImageView) view.findViewById(R.id.leftIcon);
答案 0 :(得分:32)
了解listview回收的工作原理
How ListView's recycling mechanism works
您无法回收当前正在使用的行。以上链接解释了listview回收机制的工作原理
那么使用ViewHolder有什么好处?
引用文档
在滚动ListView期间,您的代码可能会经常调用findViewById()
,这会降低性能。即使适配器返回一个膨胀的视图以进行回收,您仍然需要查找元素并更新它们。重复使用findViewById()
的方法是使用“视图持有者”设计模式。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) { // if convertView is null
convertView = mInflater.inflate(R.layout.mylayout,
parent, false);
holder = new ViewHolder();
// initialize views
convertView.setTag(holder); // set tag on view
} else {
holder = (ViewHolder) convertView.getTag();
// if not null get tag
// no need to initialize
}
//update views here
return convertView;
}
您错过了重要部分convertView.setTag(holder)
和holder = (ViewHolder) ConvertView.getTag()
http://developer.android.com/training/improving-layouts/smooth-scrolling.html
答案 1 :(得分:14)
ViewHolder
设计模式用于加速ListView
的渲染 - 实际上是为了使其顺利运行,每次渲染列表项时,findViewById都非常昂贵(它会进行DOM解析) ,它必须遍历您的布局层次结构并实例化对象。由于列表可以在滚动期间频繁地重绘其项目,因此这种开销可能很大。
您可以找到有关其工作原理的详细说明:
http://www.youtube.com/watch?v=wDBM6wVEO70&feature=youtu.be&t=7m
从第10分钟开始,您已经通过谷歌专家解释了ViewHolder的设计模式。
[编辑]
findViewById没有实例化新对象,它只遍历层次结构 - 这里是引用http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/view/ViewGroup.java#3610
答案 2 :(得分:3)
首先:
在ListView
滚动ListView
时,您需要创建新项并将其数据绑定在其上,这样如果ListView
中有大量项目,可能会导致内存泄漏,因为更多对象你为物品创建了,但Android使用了回收其大部分API的概念,这意味着你创建了一个对象并使用它而不是销毁它并声明新的对象,所以当你使用隐形项目滚动ListView
API时滚动并在getView
方法中为您传递convertView
,这样您就可以处理更多项ListView
其次:
如果您在ListView
中有自定义项目,则需要在ListView
的每个项目上附加自定义布局,这样您每次ListView
都会使用findViewById
绑定新项目获取布局项的参考。这个方法将以递归的方式搜索你的项目,这样你ViewHolder
将帮助你只进行一次递归,然后它将为你保存布局项的引用,直到你可以附加它为止ListView
希望这可以帮助你并在任何不明显的事情中反馈我