在使用ListView控件的过程中,由于加载条目过多在滑动时可能造成卡顿。这是因为List View在当前屏幕显示多少个条目,就会创建多少个对象,每一个条目都是一个对象,在滑动时,滑出屏幕的条目对象就会被销毁,新加载到屏幕上的条目就会创建新的对象,这样在list View快速滑动时就会不断地创建对象->销毁对象->创建对象,并且每一个条目都需要加载一次布局,加载布局时会不断进行findViewById()操作初始化控件,而布局xml文件是以树形结构进行加载,每次加载一个条目都需要从根节点今昔初始化,这样对内存消耗也是比较大的,并且浪费空间。如果每个条目都有图片,图片加载的时间比较长,就会造成内存溢出异常。为此就需要对ListView进行优化,优化的目的就是在滑动时不会重复创建对象,减少内存消耗和屏幕渲染处理。具体步骤如下:
①创建静态类:
创建静态类,将需要加载的控件变量放在该静态类中,保证所有控件只创建一次对象,不会重复创建对象,具体代码:
class ViewHolder{
TextView nameTV;
TextView priceTV;
ImageView imageView;
}
②复用缓存View对象:
在Adapter的getView(int i,View convertView, ViewGroup parent)方法中,第二个参数convertView代表的就是之前滑出屏幕的条目对象。如果时第一次加载该方法,会创建新的View对象,如果滑动List View,滑出屏幕的VIew对象就会以缓存的形式存在,而convert View就是缓存的View对象,可以复用缓存该对象减少新对象的创建。在加载布局时先判断convertView是否存在,如果convert View==null说明没有缓存的View对象,则使用View.inflate()方法加载布局,进行布局的初始化,否则复用缓存的view对象,具体代码:
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
//得到当前行的数据对象
ShopInfo shopInfo = data.get(i);
View view;
ViewHolder viewHolder;
if(convertView == null){
view = View.inflate(MainActivity.this,R.layout.item_main,null);
viewHolder = new ViewHolder();
viewHolder.nameTV = view.findViewById(R.id.tv_item_name);
viewHolder.priceTV = view.findViewById(R.id.tv_item_price);
viewHolder.imageView = view.findViewById(R.id.iv_item_icon);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
//设置数据
viewHolder.nameTV.setText(shopInfo.getName());
viewHolder.priceTV.setText(shopInfo.getPrice() + "元");
String imagePath = shopInfo.getImagePath();
//根据图片路径启动分线程动态请求服务加载图片并显示
imageLoader.setContext(MainActivity.this);
imageLoader.setLoadingImageRes(R.drawable.loading);
imageLoader.setErrorImageRes(R.drawable.error);
imageLoader.loadImage(imagePath,viewHolder.imageView);
return view;
}
通常getView() 方法中最后的返回值都是View,但如果复用了convent View,最后的返回值一定要改为convertView,这样才会将布局显示到页面中。