【发布时间】:2012-07-18 13:38:14
【问题描述】:
有一个简单的问题,在搜索后我想问为什么我们创建静态持有者类并在其中分配视图?请消除我的疑虑,这对我有很大帮助。
【问题讨论】:
-
您的问题是关于“静态”限定符还是一般的 ViewHolder?您是否阅读过文档:developer.android.com/training/improving-layouts/…
有一个简单的问题,在搜索后我想问为什么我们创建静态持有者类并在其中分配视图?请消除我的疑虑,这对我有很大帮助。
【问题讨论】:
在滚动ListView 期间,您的代码可能会频繁调用findViewById(),这会降低性能。即使适配器返回一个膨胀的视图进行回收,您仍然需要查找元素并更新它们。避免重复使用 findViewById() 的一种方法是使用 "view holder" 设计模式。
ViewHolder 对象将每个组件视图存储在 Layout 的标记字段中,因此您可以立即访问它们而无需重复查找它们。首先,您需要创建一个类来保存您的确切视图集。
您可以阅读Android Guideline了解更多详情。
static inner class 可以大大提高性能你也可以看到Why does Android prefer static classes链接。
还有一个有趣的链接How ListView Work,看了这篇博文后开发者可以清楚 LisView 的逻辑以及为什么需要为 listView 实现内部静态类。
【讨论】:
如果您了解AdapterView 的工作原理,答案也很简单。
AdapterView 是一个视图,其子级由 Adapter 确定。 AdapterView(更具体地说是像ListView 这样的具体实现)包含的信息比任何给定时间显示的信息都多。为了优化内存消耗和性能,Adapter 通常重用代表单个项目的Views。因此,View 对象的数量少于相应的数据。
重用对象可以是Views 或ViewGroups 的复杂层次结构。所以,如果你想从这个层次结构中找到单独的View 对象,你需要依赖findViewById() 方法,当视图层次结构有多个级别时,这会变得很昂贵。因此,为了简单起见(也为了提高性能),我们使用了 View-Holder 模式,其中我们感兴趣的单个 View 对象被分配给静态内部类。
您可以参考 Lars Vogel 的 Android ListView and ListActivity - Tutorial 了解有关 View-Holder 模式的更多信息。
【讨论】:
这是一个优化点。如果没有 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(...)
【讨论】: