ViewHolder有什么好处?

时间:2014-02-01 17:39:15

标签: android listview android-arrayadapter android-viewholder

开发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);

3 个答案:

答案 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

希望这可以帮助你并在任何不明显的事情中反馈我