스터디/Android+Java

Android ListView CheckBox로 버그 유발될때 해결 방법 - ViewHolder 사용 (2012.09.26)

Dalmangyi 2017. 10. 7.

ListView를 다룰때 커스텀으로 제작하게 되면 이상하게 에러가 많다.

그중에서도 row단에 checkbox를 붙일때! 의도치 않게 onCheckedChanged 리스너가 동작할때가 많다.


그럴때는 ViewHolder라는 protected 맴버로 구성된 Tag객체를 사용하면 된다.


모델 클레스를 기반으로 작동되는 ListAdapter를 보자.


public class Model {

    

    private String name;

    private boolean selected;

    

    public Model(String name) {

        this.name = name;

    }

    

    public String getName() {

        return name;

    }

    

    public boolean isSelected() {

        return selected;

    }

    

    public void setSelected(boolean selected) {

        this.selected = selected;

    }



public class MyAdapter extends ArrayAdapter<Model> {

    

    private final List<Model> list;

    private final Activity context;

    boolean checkAll_flag = false;

    boolean checkItem_flag = false;

    

    public MyAdapter(Activity context, List<Model> list) {

        super(context, R.layout.row, list);

        this.context = context;

        this.list = list;

    }

    

    static class ViewHolder {

        protected TextView text;

        protected CheckBox checkbox;

    }

    

    @Override

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

        

        ViewHolder viewHolder = null;

        if (convertView == null) {

            LayoutInflater inflator = context.getLayoutInflater();

            convertView = inflator.inflate(R.layout.row, null);

            viewHolder = new ViewHolder();

            viewHolder.text = (TextView) convertView.findViewById(R.id.label);

            viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.check);

            viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                

                @Override

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    int getPosition = (Integer) buttonView.getTag();  // Here we get the position that we have set for the checkbox using setTag.

                    list.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.

                }

            });

            convertView.setTag(viewHolder);

            convertView.setTag(R.id.label, viewHolder.text);

            convertView.setTag(R.id.check, viewHolder.checkbox);

            } else {

            viewHolder = (ViewHolder) convertView.getTag();

        }

        viewHolder.checkbox.setTag(position); // This line is important.

        

        viewHolder.text.setText(list.get(position).getName());

        viewHolder.checkbox.setChecked(list.get(position).isSelected());

        

        return convertView;

    }

}



여기서 중요한건 viewHolder와 onCheckedChaned() Override함수에서 getTag()를 통한 position과 setTag를 잘 보면 된다.



참고 : http://www.lalit3686.blogspot.in/2012/06/today-i-am-going-to-show-how-to-deal.html

댓글