RecycleView的复用是一剂解药,也是一剂毒药。
复用可解ListView的性能问题,但也会带来RecycleView所特有的附加伤害。
解RecycleView的办法大概分为3种:
1,禁用其复用功能,即 ViewHolder.setIsRecyclable(false); (这样做会使RecycleView失去其本身的特性,不推荐)
2,给数据源加一个属性,然后在状态变更时修改数据源,或者单选情况使用一个变量存储选中的位置,最后使用notifyDataSetChanged();来刷新数据。需要注意的是,如果当数据特别多时,这个代价就很大了。操作如下
bean中:
private boolean isSelected=false;
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
数据源修改时:
fileListItemBean.setSelected(true);
notifyDataSetChanged();
3,List和Tag配合使用,效果最佳。
RecycleView在滑动屏幕的时候,会对即将显示的view进行一个处理,此时会回调
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i)
一般情况下,当你的数据是从数据源中取得,且用于单选,条目不多,可使用第二种解法,但如果遇到一个带CheckBox的多选需求,而且条目多时,你可能就得考虑下这种繁琐的解法:
步骤一:选一个带唯一性的tag,一般选用position,将其存入一个view控件中
viewHolder.checkCb.setTag(position);
步骤二:新建一个list容器
private List<Integer> mSelectedPos = new ArrayList<>();
并在该view的点击事件中进行逻辑处理,这里是checkBox,所以需要考虑到手动设置checked时触发到的OnCheckedChangeListener回调。
//onBindViewHolder代码块
listViewHolder.checkCb.setChecked(mSelectedPos.contains(
position));
listViewHolder.checkCb.setOnCheckedChangeListener((compoundButton, isSelected) -> {
if (isSelected) {
if (!mSelectedPos.contains(viewHolder.checkCb.getTag())) {
mSelectedPos.add(position);
}else {
//防止多次触发 如果当前为选中 则直接返回 不需要执行其他操作
return;
}
} else {
if (mSelectedPos.contains(viewHolder.checkCb.getTag())) {
//请注意这里需要使用Integer.valueOf 的方式,因为list中是
Integer,是一个装箱的对象,这时候直接用pos会将其作为数组下标发生数组越界
mSelectedPos.remove(Integer.valueOf(position));
}else {
//防止多次触发 如果当前为未选中则直接返回 不需要执行其他操作
return;
}
}
});
如果你有获取选中对象的需求,建议你再建一个list数组对象,将你选中的数据均加入到该list中。像这样:
//onBindViewHolder代码块
listViewHolder.checkCb.setChecked(mSelectedPos.contains(
position));
listViewHolder.checkCb.setOnCheckedChangeListener((compoundButton, isSelected) -> {
if (isSelected) {
if (!mSelectedPos.contains(viewHolder.checkCb.getTag())) {
mSelectedPos.add(position);
mSelectedDatas.add(mDatas.get(position));
}else {
//防止多次触发 如果当前为选中 则直接返回 不需要执行其他操作
return;
}
} else {
if (mSelectedPos.contains(viewHolder.checkCb.getTag())) {
//请注意这里需要使用Integer.valueOf 的方式,因为list中是
Integer,是一个装箱的对象,这时候直接用pos会将其作为数组下标发生数组越界
mSelectedPos.remove(Integer.valueOf(position));
mSelectedDatas.remove(mDatas.get(position));
}else {
//防止多次触发 如果当前为未选中则直接返回 不需要执行其他操作
return;
}
}
});
以上。
本站由以下主机服务商提供服务支持:
0条评论