arrayAdapter getView方法中的监听器

时间:2012-12-29 16:14:07

标签: android listview listener

我有一个ListViews的自定义row_item,带有图像,一对TextView和一个复选框。 根据我的理解,因为checkBox是一个可聚焦的元素,它会从listView中窃取焦点,所以OnListItemClicked永远不会被触发,除非我将每个row_item设置为不可点击并阻止后代的可聚焦性。

然后,为了管理checkBoxes更改,我在我的适配器getView方法中为我的checkBox设置了一个“OnCheckedChangeListener”。

这是一个不好的方法吗? (因为每次调用getView时我都会创建新的监听器) 还有其他方法可以做同样的事吗?

我附上一些代码,以便更容易理解我的意思。

getView方法:(在arrayAdapter中)

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    /** recycling views */
    View row = convertView;
    PregoHolder holder = null;

    if(row == null)
    {
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);

        holder = new PregoHolder();
        holder.imgIcon = (ImageView)row.findViewById(R.id.thumbnail);
        holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
        holder.txtNews = (TextView)row.findViewById(R.id.txtNews);
        holder.chBox = (CheckBox) row.findViewById(R.id.checkBox);

        row.setTag(holder);
    }
    else
    {
        holder = (PregoHolder)row.getTag();
    }

    Prego Prego = data[position];
    holder.txtTitle.setText(Prego.title);
    holder.imgIcon.setImageResource(Prego.icon);
    holder.txtNews.setText(Prego.news);
    holder.chBox.setChecked(Prego.checked);

    /** wiring up Listeners... 
     * (works fine but we are creating new listener each time)
     * (Done like this because of the custom list view focusable issue)
     */

    holder.chBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

        @Override
        public void onCheckedChanged(CompoundButton arg0, boolean checked) {
            /** Getting the view position in the ListView */
            ListView parent = (ListView)(arg0.getParent()).getParent();
            int pos = parent.getPositionForView(arg0);

            if (checked){
                checkedPregons[pos] = true;
                pregonsChecked++;
            }
            else if (!checked){
                checkedPregons[pos] = false;
                pregonsChecked--;
            }

            Toast.makeText(context, pregonsChecked+" is/are checked", Toast.LENGTH_SHORT).show();
        }
    });

    row.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            //mMode = ((Activity)context).startActionMode(new PregonsActionModes());
            ListView parent = (ListView)v.getParent();
            int pos = parent.getPositionForView(v);
            Toast.makeText(context, "getView should show prego "+pos,Toast.LENGTH_SHORT).show();

        }
    });

    return row;
}

提前致谢。

1 个答案:

答案 0 :(得分:3)

我想可能有更好的方法来解决这个问题,但这不是我失眠的原因。你的方法是由许多新旧开发人员疯狂实现的,这只是一种简单的自然方式。此外,请记住,ListView一次只有你在屏幕上看到的行数(滚动时不断调用getView),所以你说的是8 - 12在任何给定时间制造物体(显然完全猜测),所以你的瓶颈不会在这里。事实上,根据我需要修改的对象的位置,我甚至没有想到它。

OnCheckedChangeListener中使用ListView是我强烈反对的事情。就像我说的那样,每一行都会调用getView,因为它正在滚动和制作。这个已检查的已更改的侦听器正在被激活时被触发,尽管绝对不能保证getView每行只调用一次 ,实际上我保证不会这样做。因此,这些代码块可能会被唤醒wazoo,即使您可能只是在手动处理CheckBox框勾选时才打算这样做。加上一个相对更密集的命令,如notifyDataSetChanged(),你会看到你的ListView锁定了这个现象。

解决方案是简单地使用复选框onClickListener并检查内部的isChecked()