服务器之家

服务器之家 > 正文

ListView的View回收引起的checkbox状态改变监听等问题解决方案

时间:2021-01-05 11:57     来源/作者:Android教程网

之前讲到了自定义Adapter传递给ListView时,因为ListView的View回收,需要注意当ListView列表项中包含有带有状态标识控件的问题。详情可见之前发的帖[url=自定义Adapter实现ListView带多选框等状态控件的注意事项 https://www.zzvips.com/article/129051.html
还是这个问题,讲一个我遇到的因为两行代码位置相反引起的问题。
我的ListView中每行View包含一个ImageView、TextView、CheckBox。当ListView中有一个或一个一行CheckBox被选中就让ListView上面的Button显示,否则就隐藏。因此,需要对每行View中的CheckBox设置监听。我使用CheckBox中的OnCheckedChangeListener监听器,当CheckBox的状态发生改变的时候就会触发这个监听器。先看下我自定义给ListView的Adapter的getView方法中的一些关键代码:
这是getView方法中使用到的内部类:

复制代码 代码如下:


static class ViewHolder {
public ImageView imageView;
public TextView textView;
public CheckBox checkBox;
}


这是getView方法中利用ListView回收机制循环利用View的代码:

复制代码 代码如下:


public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.searchitem, null);
viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) convertView
.findViewById(R.id.searchitemimage);
viewHolder.textView = (TextView) convertView
.findViewById(R.id.searchitemtext);
viewHolder.checkBox = (CheckBox) convertView
.findViewById(R.id.searchitemcheckbox);
convertView.setTag(viewHolder);
} else {
// Log.i(CodeUtils.SEARCHTAG, "view is reuse");
viewHolder = (ViewHolder) convertView.getTag();
}


接下来是对其中checkbox设置显示状态和监听器的代码:

复制代码 代码如下:


viewHolder.checkBox
.setOnCheckedChangeListener(new SearchItemOnCheckedChangeListener(
position, state));
viewHolder.checkBox.setChecked(state[position]);


之前说过了,因为ListView的回收,需要使用一个数组或list来记录每项数据中checkbox的状态。这里,state是与ListView列表等长的boolean数组,用于记录每个position(也就是每个列表项数据的id)标识的数据上checkbox应该显示的状态,初始的状态都是false。构造checkbox监听器的时候需要传递当前View的position,以及整个列表checkbox的状态数组state。以下是checkBox状态改变监听器的代码:

复制代码 代码如下:


public class SearchItemOnCheckedChangeListener implements
OnCheckedChangeListener {
private int id;
private Boolean[] state;
public SearchItemOnCheckedChangeListener(int id, Boolean[] state) {
this.id = id;
this.state = state;
}
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
state[id] = isChecked;
if (isChecked) {
checkedCount++;
}else{
checkedCount--;
}
if (checkCoutn>0) {
searchButton.setVisibility(Button.INVISIBLE);
} else {
searchButton.setVisibility(Button.VISIBLE);
}
}
}
}


这里面checkedCount初始值为0的整型,用于记录被选中多选框的数量。searchButton是根据checkbox而决定显示还是隐藏的按钮。

以上整个逻辑功能的实现代码。开头说了,这是一个我因为ListView的回收机制和两行代码位置相反引起的问题。两行代码的位置相反将导致完全不同的结果,所指的就是设置checkbox监听器和状态的两行代码,起初我的顺序为:

复制代码 代码如下:


viewHolder.checkBox.setChecked(state[position]);
viewHolder.checkBox.setOnCheckedChangeListener(new SearchItemOnCheckedChangeListener(position, state));


这样的顺序出现的问题是,当我拉动列表后,因为拉动被隐藏的列表项状态将被更改为false。这很不可思议,因为我已经分离了一个状态数组来记录每个checkbox的状态,想来想去只有一个可能,就是状态数组中的值改变了,而改变状态数组的值位置就在于OnCheckedChangeListener中。Debug了几个小时,才想通了问题就在于这两行代码为位置顺序。

起因还是得讲到ListView的回收机制。假如我的ListView最多只能显示10个View,那么起初就会调用十次getView构造十个全新的View(包括对其中的checkbox设置监听器)。当我将列表往下拉出现第11个列表项的时候,顶部第一个列表项被隐藏,同样会再调用一次getView,不过此时getView的参数将返回刚刚被隐藏的第一个列表项的View,并对这个View更改数据作为即将出现的第11个View。问题就出在这里,我把checkbox.setChecked()方法调用放在了设置监听器前面,此时因为更改了checkbox的状态,势必引起触发状态更改的监听器。注意!由于第11个View是用被隐藏的第1个View回收来的,虽然还没有执行下一行设置监听器的代码,但实际上它已经拥有了一个状态监听器,这个监听器是这个View还是作为第一个View时设置。那个时候的监听器设置更改的第一项的数据,而不是第11项数据。因此,理所当然不能正确更改第11项数据,反而更改了无辜的第1项数据。如果我把两行代码顺序反过来,先更改监听器,再设置状态,引发的监听器自然也就是新的监听器,逻辑也就对了。

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
电视剧《琉璃》全集在线观看 琉璃美人煞1-59集免费观看地址
电视剧《琉璃》全集在线观看 琉璃美人煞1-59集免费观看地址 2020-08-12
返回顶部

504
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40