有一个简单的问题,在搜索后我想问为什么我们创建静态持有者类并在其中分配视图?请明确我的怀疑对我来说会有很大的帮助。
答案 0 :(得分:7)
您的代码可能会在滚动findViewById()
期间经常调用ListView
,这会降低性能。即使适配器返回一个膨胀的视图以进行回收,您仍然需要查找元素并更新它们。重复使用findViewById()
的方法是使用 "view holder"
设计模式。
ViewHolder
对象将每个组件视图存储在Layout的标记字段中,因此您可以立即访问它们,而无需重复查找它们。首先,您需要创建一个类来保存您的确切视图集。
您可以阅读Android Guideline了解更多详情。
static inner class
可以大大提高效果您还可以看到Why does Android prefer static classes链接。
另一个有趣的链接How ListView Work ,在阅读此博客开发人员后可以清除LisView的逻辑以及为什么需要为listView实现内部静态类。
答案 1 :(得分:2)
如果您了解AdapterView
的工作原理,答案也很简单。
AdapterView
是一个视图,其子项由Adapter
确定。 AdapterView
(更具体地说,像ListView
这样的具体实现)包含的信息比任何给定时间显示的信息都多。为了优化内存消耗并且为了性能,Adapter
通常会重用代表各个项目的View
。因此,View
个对象的数量少于相应的数据。
重用的对象可以是View
s或ViewGroups
的复杂层次结构。因此,如果要从此层次结构中查找单个View
对象,则需要依赖findViewById()
方法,当视图层次结构具有多个级别时,这会变得很昂贵。因此,为简单起见(以及提高性能),使用View-Holder模式,将我们感兴趣的各个View
对象分配给静态内部类。
有关View-Holder模式的更多信息,请参阅Lars Vogel的Android ListView and ListActivity - Tutorial。
答案 2 :(得分:1)
这是一个优化点。如果没有viewHolder,您每次都需要调用findViewById方法。使用viewHolder,您只需要调用一次。
使用TextView和ImageView的示例:
没有ViewHolder:
if (convertView == null) {
convertView = mInflater.inflate(..., null);
}
//Following called each time
TextView tv = (TextView)convertView.findViewById(...);
ImageView iv = (ImageView)convertView.findViewById(...);
tv.setText(...)
使用ViewHolder:
if (convertView == null) {
convertView = mInflater.inflate(..., null);
holder = new ViewHolder();
//called once
holder.tv = (TextView) vi.findViewById(..);
holder.iv = (ImageView) vi.findViewById(...);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
holder.tv.setText(...)