谈谈RecycleView复用的三种解法


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;
}
}
});

以上。

声明:TIL|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA[ZH]协议进行授权

转载:转载请注明原文链接 - 谈谈RecycleView复用的三种解法


Life is very interesting. In the end, some of your greatest pains become your greatest strengths.