【发布时间】:2016-01-22 05:10:47
【问题描述】:
什么时候应该使用ViewHolder?我在ListView 和GridView 的大多数代码中发现了这一点。如果有人能解释一下。
谢谢。
【问题讨论】:
-
谢谢。 AKSiddique
标签: android baseadapter
什么时候应该使用ViewHolder?我在ListView 和GridView 的大多数代码中发现了这一点。如果有人能解释一下。
谢谢。
【问题讨论】:
标签: android baseadapter
ViewHolder 模式有什么用?
ViewHolder 设计模式使您无需查找即可访问每个列表项视图,从而节省宝贵的处理器周期。具体来说,它避免了在 ListView 滚动过程中频繁调用 findViewById() ,这将使其平滑。
没有 ViewHolder 设计模式
看看我们之前在ArrayAdapterItem.java中的getView()方法
第一次加载时,convertView 为空。我们必须扩充列表项布局并通过 findViewById() 找到 TextView。
第二次加载,convertView不为空,好!我们不必再给它充气。但我们会再次使用 findViewById()。
以下几次加载,convertView肯定不为null。但是 findViewById() 经常被调用,它会起作用,但是它会降低性能,尤其是当 ListView 中有很多项目和视图时。
使用 ViewHolder 设计模式
现在让我们看看它是如何与 ViewHolder 模式一起工作的。
第一次加载时,convertView 为空。我们必须扩充列表项布局,实例化 ViewHolder,通过 findViewById() 找到 TextView 并将其分配给 ViewHolder,并将 ViewHolder 设置为 convertView 的标记。
第二次加载,convertView不为空,好!我们不必再给它充气。好消息是,我们不必调用 findViewById(),因为我们现在可以通过其 ViewHolder 访问 TextView。
接下来加载的时候,convertView肯定不为null。 findViewById() 不再被调用,这使得我们的 ListView 滚动顺畅。
通过Android Adapter 和 ViewHolder Pattern 了解更多详细示例。
正式,
为什么是观众?
因为,将视图对象保存在 View Holder 中
您的代码可能会在滚动过程中频繁调用 findViewById() ListView,这会降低性能。即使当适配器 返回一个膨胀的视图进行回收,你仍然需要查找 元素并更新它们。重复使用 findViewById() 的一种方法 就是使用“view holder”设计模式。
ViewHolder 对象将每个组件视图存储在标签内 布局的字段,因此您可以立即访问它们而无需 需要反复查找。首先,您需要创建一个类 保留您的确切观点。
例如:
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
然后填充 ViewHolder 并将其存储在布局中。
ViewHolder holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image);
holder.text = (TextView) convertView.findViewById(R.id.listitem_text);
holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp);
holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner);
convertView.setTag(holder);
现在您无需查找即可轻松访问每个视图,从而节省宝贵的处理器周期。
【讨论】:
什么时候? 如果你想让你的列表视图平滑滚动并且它应该是响应式的。
为什么? 当您使用 ViewHolder 模式时,不是每次滚动时都创建自定义行,而是重用向下滚动时隐藏的布局视图。 否则,您将一直在夸大您的自定义 lsitview 布局行,这会使 UI 无响应,并且可能会显示弹出对话框,例如应用程序没有响应并显示 ok 和取消选项。
【讨论】: