实现功能:当GridView 大小固定的时候,内部显示大量的checkbox,超出GridView区域的时候,这时我们就需要通过上下滚动来找到我们需要的内容进行勾选。当选中的时候不管是下拉刷新增加新的item还是上拉加载出更多的item都需要保持原来选中的状态,另外新增加的item和加载的item都需要像其它item一样可以对CheckBox进行操作,
问题:当选中一个的时候,然后上下滑动,会发现下面没有被选择的也会被勾选,此时页面显示的已勾选的内容和之前选中的是不一致的。这样很影响使用,那么怎么解决呢?
复用原理:GridView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。
Android提供了一个叫做Recycler(反复循环器)的构件,就是当GridView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。
由于在使用GridView时为了减少对内存的消耗,因此在自定义适配器的时候为了优化GridView都会复用View,这样的话就会造成前面选中CheckBox时后面复用的item的CheckBox也会被选中的问题
如果一个屏幕最多显示7个Item,当Item1滑出屏幕,此时Item1 的View被添加进Recycler中,相应的在下部要产生一个Item8,这时调用getView方法,convertView参数就是Item1 的View。
GridView的复用虽然大大提升了性能,但是却也带来很多问题。比如在加载图片时,由于下边的item复用了上边的item,造成下边item刚加载出来时显示的还是上边被复用的item的图片,等到这个新的item加载图片完毕时才会正常显示,这就是convert view复用造成GridView图片加载错乱的问题。
适配器
public class sureAdapter extends BaseAdapter {
private Contextmeasure Context;
private List
//用来控制checkBox的选中状况
private static HashMap isSelected;
private LayoutInflater inflater =null;
//传过来的checkbox的选中状况数组
boolean[]statas;
public sureAdapter(Context context, List
measureContext = context;
measureList = list;
inflater = LayoutInflater.from(context);
isSelected =new HashMap();
this.statas =statas;
}
@Override
public int getCount() {
return measureList.size();
}
@Override
public Object getItem(int i) {
return measureList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder =null;
if (view ==null) {
viewHolder =new ViewHolder();
view = LayoutInflater.from(measureContext).inflate(R.layout.list_measure,null);
viewHolder.cb_state=view.findViewById(R.id.cb_state);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.cb_state.setText(measureList.get(i).FName);
//setOnCheckedChangeListener事件是屏幕滚动事件,当需要上下滑动的事件,调用此事件,避免checkbox显示混乱的问题出现
viewHolder.cb_state.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if(isChecked==true){
isSelected.put(i,true);
}else {
isSelected.remove(i);
}
}
});
//checkbox的点击事件:activity调用此方法,然后执行一些特殊操作
viewHolder.cb_state.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
measureListener.onDeleteClick(i);
}
});
if(isSelected!=null&&isSelected.containsKey(i)){
viewHolder.cb_state.setChecked(true);
}else {
viewHolder.cb_state.setChecked(false);
}
return view;
}
/**
* checkbox选择状态的监听接口
*/
public interface onItemDeleteListener {
void onDeleteClick(int i);
}
private onItemDeleteListenermeasureListener;
public void setmeasureClickListener(onItemDeleteListener measureOnItemListener) {
this.measureListener = measureOnItemListener;
}
public static class ViewHolder {
public CheckBoxcb_state;
}
public static HashMap getIsSelected() {
return isSelected;
}
public static void setIsSelected(HashMap isSelected) {
sureAdapter.isSelected = isSelected;
}
}
activity代码
private sureAdapter adapter;
private GridView gr_feature;
adapter =new sureAdapter(MeasureActivity.this,dto);
gr_feature.setAdapter(adapter);
adapter.setmeasureClickListener(new sureAdapter.onItemDeleteListener(){
@Override
public void onDeleteClick(int i) {
if(floorState[i] ==true){
floorState[i] =false;
localinfo[i]="";
txt_location.setText("");
for (int j=0;j
if(floorState[j]==true){
txt_location.setText(txt_location.getText().toString()+localinfo[j]+""+dto.get(j).FName+";");
}
}
}else{
floorState[i] =true;
addlocalinfo(i);
}
adapter.notifyDataSetChanged();
}
});