关于ListView中CheckBox选择混乱的问题

遇到了这个问题,记录下,方便以后查看,也让道友们看看

先上整体代码

public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private List<Entity> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.listView);

        initData();

        listView.setAdapter(new MyAdapter(this,list));


    }

    private void initData() {
        list = new ArrayList<>();
        for (int i = 0; i < 20; i++){
            Entity entity = new Entity();
            entity.isChecked = false;
            entity.text = "这是第"+i+"条数据";
            list.add(entity);
        }
    }

    private class MyAdapter extends BaseAdapter{

        private Context context;
        private List<Entity> list;

        MyAdapter(Context context,List<Entity> list){
            this.context = context;
            this.list = list;
        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position,View convertView,ViewGroup,parent){
            ViewHolder holder;
            if (convertView == null){
                convertView = LayoutInflater.from(context)
                        .inflate(R.layout.list_item,parent,false);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder) convertView.getTag();
            }
            final Entity data = list.get(position);
            holder.checkBox.setChecked(data.isChecked);
            holder.text.setText(data.text);
            holder.checkBox.setOnCheckedChangeListener(
                        new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    data.isChecked = isChecked;
                }
            });
            return convertView;
        }

        class ViewHolder{

            TextView text;
            CheckBox checkBox;

            public ViewHolder(View convertView){
                text = (TextView) convertView.findViewById(R.id.title);
                checkBox = (CheckBox) convertView
                                .findViewById(R.id.checkbox);
            }

        }
    }

}

整体布局很简单,LinearLayout中放个ListView

ListView中的Item布局就是在LinearLayout中放了个TextView和一个CheckBox

如果不是用ViewHolder的话,是没问题的(可以自己试下),
上面通过ViewHolder来优化,出现选择混乱问题。

解决办法:
将holder.checkBox.setChecked(data.isChecked);
语句放在CheckBox选择改变监听事件后面,即可解决

原因分析

    我们通过ViewHolder重用convertView,这时对于第一个条目,
我们选中后,滑动ListView,下面出来的item会重用第一个消息item的布局

        再看我们的代码,每次根据list中对应position初始化checkbox状态,
        看着好像也没问题,但是事实出现了问题...

    一直以为是重用convertView的时候系统会给我们重置一些状态,后来发现不是...

我们勾选第一个item的 checkbox,然后滑动ListView到第一个条目消失,
这时最下面的item是重用第一个item的布局的,
这时我们初始化布局信息或状态,但是在初始化CheckBox状态时,使用的数据
为list中对应position的数据,此时监听事件还未重置,
监听事件改变的数据依旧是list中第一个数据,导致初始化CheckBox的时候
将第一个条目的数据也改变了所以导致滑动回来后,之前选择的取消选择了

    因此将初始化CheckBox状态的语句放在设置完监听事件后就正常了。

猜你喜欢

转载自blog.csdn.net/qq_34696209/article/details/73312677