使用ListView控件的过程中,由于加载条目过多在滑动时可能造成卡顿。这是因为ListView在当前屏幕显示多少个条目,就会创建多少个对象,每一个条目都是一个对象。在滑动时,滑出屏幕的条目对象会被销毁,新加载到屏幕上的条目会创建新的对象,这样在ListView快速滑动时就会不断的【创建对象】-->【销毁对象】-->【创建对象】,并且每一个条目都需要加载一次布局,加载布局时会不断进行findViewById()操作初始化控件,而布局XML文件是以树形进行加载,每次加载一个条目都需要从根节点进行初始化,这样对内存消耗也比较大,并且浪费时间。如果每个条目都有图片,图片加载的时间比较长,就会造成内存溢出异常。为此就需要对ListView进行优化,优化的目的是在滑动时不会重复创建对象,减少内存消耗和屏幕渲染处理。具体步骤如下:
1)创建静态类
创建一个静态类,将需要加载的控件变量放在该静态类中,保证所有控件只创建一次对象,不会重复创建对象,具体代码如下所示:
static class ViewHolder{
TextViewmNameTV;
TextViewmPhoneTV;
}
2)复用缓存View对象
在Adapter的getView(int position, ViewconvertView, ViewGroup parent)方法中,第二个参数convertView代表的就是之前滑动出屏幕的条目对象。如果是第一次加载该方法时,会创建新的View对象,如果滑动ListView时,滑动出屏幕的View对象会以缓存的形式存在,而convertView就是缓存的View对象,我们可以复用缓存该对象减少新对象的创建。在加载布局时先判断convertView是否存在,如果convertView==null说明没有缓存的View对象,则使用View.inflate()方法加载布局,进行布局的初始化,否则复用缓存的View对象。
如果复用了缓存的View对象,也就是convertView,滑动时当前屏幕的条目可能和之前划出屏幕的条目使用的是同一个对象,这样就可能造成出现重复条目等异常,因此需要对convertView进行setTag()设置将holder绑定到了view上,以确定当前显示的是哪一个条目,防止出现重复条目。具体代码如下所示:
if(convertView == null){
convertView= View.inflate(context, R.layout.item_list_contact_select, null);
holder =new ViewHolder();
holder.mNameTV= (TextView) convertView.findViewById(R.id.tv_name);
holder.mPhoneTV= (TextView) convertView.findViewById(R.id.tv_phone);
convertView.setTag(holder);
}else{
holder =(ViewHolder) convertView.getTag();
}
|
|