ArrayAdapter 上的 ViewHolder 缓存模式具有连锁反应
ViewHolder cache pattern on ArrayAdapter has ripple effects
我一直在关注 ListView 的 ViewHolder 模式,在代码下方。实际上它运行良好 - 但我有一个问题。
我在适配器中的项目具有以下布局:
================================================================
| Item title |AddIcon|RemoveIcon|EditIcon|
================================================================
问题如下:当我点击 RemoveIcon 时,代码运行后,我想让 RemoveIcon 改变颜色。我在下面代码的倒数第二行使用 setImageResource 执行此操作。现在也可以正常工作 - 图标已更改。但是现在,当我滚动时,在每个特定的时间间隔(在我的 phone 上它是 8 个项目),图标也会发生变化。缓存似乎在这里发挥作用?
问题:
- 当每个项目的布局基本上都是单独的时,我可以使用此缓存吗?
如果我不能,是否可以使用未缓存的布局并为每个项目重复它?目前我的列表中可能有大约 100 个项目。有更好的方法吗?
public class ItemListAdapter extends ArrayAdapter<StoreItem> {
static class ViewHolder {
public TextView title;
public ImageButton more;
public ImageButton less;
public ImageButton edit;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = mContext.getLayoutInflater();
rowView = inflater.inflate(R.layout.item_layout, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.title = (TextView) rowView.findViewById(R.id.title);
viewHolder.more = (ImageButton) rowView.findViewById(R.id.item_mas);
viewHolder.less = (ImageButton) rowView.findViewById(R.id.item_menos);
viewHolder.edit = (ImageButton) rowView.findViewById(R.id.item_edit);
rowView.setTag(viewHolder);
}
final ViewHolder holder = (ViewHolder) rowView.getTag();
final StoreItem item = mItems.get(position);
holder.title.setText(item.getTitle());
holder.less.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//dialog is a confirmation dialog, initialization omittted for brevity
dialog.setConfirmClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
removeItem(item, v);
holder.less.setImageResource(R.drawable.x_ok);
dialog.getDialog().cancel();
}
});
}
});
物品的颜色是一种状态。使用任何类型的缓存模式(例如 View Holder 模式)时,您必须确保在设置视图时表示该状态。
这里的问题不是您在点击时将可绘制对象更改为 R.drawable.x_ok
,而是您在初始设置中没有考虑未点击状态。
首先,将状态保存在您的 Holder 对象中
public void onClick(View v) {
removeItem(item, v);
holder.setLessClicked(true);
holder.less.setImageResource(R.drawable.x_ok);
dialog.getDialog().cancel();
}
现在,无论何时通过 getView 方法,都正确应用该状态:
final ViewHolder holder = (ViewHolder) rowView.getTag();
final StoreItem item = mItems.get(position);
holder.title.setText(item.getTitle());
if(holder.isLessClicked()){
holder.less.setImageResource(R.drawable.x_ok);
}
else{
holder.less.setImageResource(R.drawable.x_normal);
}
要记住的重要部分是 else 条件。您现在正确地设置了两种状态,即为每个可能的行单击和未单击。而之前,除了您点击的单元格之外,您没有正确处理所有其他单元格的未点击状态。
我一直在关注 ListView 的 ViewHolder 模式,在代码下方。实际上它运行良好 - 但我有一个问题。
我在适配器中的项目具有以下布局:
================================================================
| Item title |AddIcon|RemoveIcon|EditIcon|
================================================================
问题如下:当我点击 RemoveIcon 时,代码运行后,我想让 RemoveIcon 改变颜色。我在下面代码的倒数第二行使用 setImageResource 执行此操作。现在也可以正常工作 - 图标已更改。但是现在,当我滚动时,在每个特定的时间间隔(在我的 phone 上它是 8 个项目),图标也会发生变化。缓存似乎在这里发挥作用?
问题:
- 当每个项目的布局基本上都是单独的时,我可以使用此缓存吗?
如果我不能,是否可以使用未缓存的布局并为每个项目重复它?目前我的列表中可能有大约 100 个项目。有更好的方法吗?
public class ItemListAdapter extends ArrayAdapter<StoreItem> { static class ViewHolder { public TextView title; public ImageButton more; public ImageButton less; public ImageButton edit; } @Override public View getView(final int position, View convertView, ViewGroup parent) { View rowView = convertView; // reuse views if (rowView == null) { LayoutInflater inflater = mContext.getLayoutInflater(); rowView = inflater.inflate(R.layout.item_layout, parent, false); ViewHolder viewHolder = new ViewHolder(); viewHolder.title = (TextView) rowView.findViewById(R.id.title); viewHolder.more = (ImageButton) rowView.findViewById(R.id.item_mas); viewHolder.less = (ImageButton) rowView.findViewById(R.id.item_menos); viewHolder.edit = (ImageButton) rowView.findViewById(R.id.item_edit); rowView.setTag(viewHolder); } final ViewHolder holder = (ViewHolder) rowView.getTag(); final StoreItem item = mItems.get(position); holder.title.setText(item.getTitle()); holder.less.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //dialog is a confirmation dialog, initialization omittted for brevity dialog.setConfirmClickListener(new View.OnClickListener() { @Override public void onClick(View v) { removeItem(item, v); holder.less.setImageResource(R.drawable.x_ok); dialog.getDialog().cancel(); } }); } });
物品的颜色是一种状态。使用任何类型的缓存模式(例如 View Holder 模式)时,您必须确保在设置视图时表示该状态。
这里的问题不是您在点击时将可绘制对象更改为 R.drawable.x_ok
,而是您在初始设置中没有考虑未点击状态。
首先,将状态保存在您的 Holder 对象中
public void onClick(View v) {
removeItem(item, v);
holder.setLessClicked(true);
holder.less.setImageResource(R.drawable.x_ok);
dialog.getDialog().cancel();
}
现在,无论何时通过 getView 方法,都正确应用该状态:
final ViewHolder holder = (ViewHolder) rowView.getTag();
final StoreItem item = mItems.get(position);
holder.title.setText(item.getTitle());
if(holder.isLessClicked()){
holder.less.setImageResource(R.drawable.x_ok);
}
else{
holder.less.setImageResource(R.drawable.x_normal);
}
要记住的重要部分是 else 条件。您现在正确地设置了两种状态,即为每个可能的行单击和未单击。而之前,除了您点击的单元格之外,您没有正确处理所有其他单元格的未点击状态。