为什么BaseAdapter getview在行中混合我的数据



我正在使用BaseAdapter来定制我的listview

public View getChildView(int groupPosition, int childPosition,
                boolean isLastChild, View view, ViewGroup parent) {
            if (view == null) {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.products_item, null);
            }
            FileBean file = (FileBean) ((ExtendedList) (Object) categories.get(groupPosition)).getItem(childPosition);
            CheckBox checkBox = (CheckBox) view.findViewById(R.id.fileCheckBox);
            if(checkBox != null){
                if(mCheckBoxListener != null){
                    checkBox.setOnCheckedChangeListener(mCheckBoxListener);
                }
                checkBox.setChecked(file.isChecked());
                Log.d("getcview", String.valueOf(file.isChecked() + " " + file.getName() 
                        + " " + groupPosition + " "  + childPosition));
            }
            setProductDetails(file, view);
            ViewHolder holder = new ViewHolder();
            holder.groupPosition = groupPosition;
            holder.childPosition = childPosition;
            Log.d("exadapter", "Child " + file.getName());
            view.setTag(holder);
            return view;
        }

您的问题与滚动列表视图时视图被回收有关。你必须每次重置正确的值为你的复选框(选中或未选中)。

你正在这样做,但是你的顺序是错误的,你的OnCheckListener被触发每次你重置复选框已选中/未选中的值(你先设置侦听器,然后你改变复选框的值)。

  1. 删除OnCheckListener
  2. 设置复选框值
  3. 再次添加监听器

正确顺序:

checkBox.setOnCheckedChangeListener(null);
checkBox.setChecked(file.isChecked());
checkBox.setOnCheckedChangeListener(mCheckBoxListener)

在baseadapter类中重写这两个方法:

@Override
    public int getViewTypeCount() {
        if (getCount() != 0)
            return getCount();
        return 1;
    }
    @Override
    public int getItemViewType(int position) {
        return position;
    }

看看它是否有效。

我看到两个问题,

1 -将你的LayoutInflater移出getView方法,你在那里创建了很多垃圾。相反,应该创建一个实例变量来存储LayoutInflater,并在适配器的构造函数中创建它。(顺便说一句,这与混合无关)。

private LayoutInflater mInflater; //instance variable
public CustomAdapter(Context context, List<Item> items) {
    //some code
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

2 -每次调用getView()时,都在上创建ViewHolder实例。移动这段代码:

ViewHolder holder = new ViewHolder();
holder.groupPosition = groupPosition;
holder.childPosition = childPosition;
Log.d("exadapter", "Child " + file.getName());
view.setTag(holder);

在converview的空检查中。您只希望在converView为null时(仅在新视图上)创建一个新的ViewHolder。

public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View view, ViewGroup parent) {
    //First, get the Tag from the converView
    ViewHolder mHolder = (ViewHolder) view.getTag();
    //Now check if the holder is null, rather than checking if the convertView is null.
    if (mHolder == null) {
        //init the holder code
        view.setTag(mHolder);  //only set the Tag if it's a new view.
    }

同样,你以错误的方式使用ViewHolder模式,你应该使用ViewHolder来存储CheckBox,例如,所以你不必在每个getView调用上调用findViewById(R.id.fileCheckBox);

希望有帮助。

最新更新