ArrayAdapter上的ViewHolder缓存模式具有连锁效应

时间:2015-05-15 16:21:31

标签: android android-listview android-arrayadapter android-viewholder

我一直在代码下面跟随ListView的ViewHolder模式。实际上它运作良好 - 但我有一个问题。

适配器中的我的项目具有以下布局:

================================================================
|    Item title                    |AddIcon|RemoveIcon|EditIcon|
================================================================

问题如下:当我点击RemoveIcon时,代码运行后,我希望RemoveIcon改变颜色。我使用setImageResource在下面代码的倒数第二行中执行此操作。现在也工作正常 - 图标已更改。但现在,当我滚动时,在每个特定的时间间隔(在我的手机上它的8个项目),图标也会改变。看起来像在这里缓存踢?

问题:

  1. 当布局基本上是每个项目的个别时,我可以使用此缓存吗?
  2. 如果我可能不能,可以使用未缓存的布局并为每个项目重复它吗?目前我可能在列表中有大约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();
                        }
                    });
                }
            });
    

1 个答案:

答案 0 :(得分:1)

项目的颜色是一种状态。使用任何类型的缓存模式时,例如View Holder模式,您必须确保在设置视图时表示该状态。

此处的问题不是您在点击时将drawable更改为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);
}

要记住的重要部分是其他条件。您现在正在为每个可能的行正确设置两个状态,单击和未单击。而在此之前,除了您点击的单元格之外,您还没有正确处理所有其他单元格的未单击状态。