1.重用ConvertView
ListView的View回收机制:在可视范围上面或者下面的View加入到回收池中。当在可视范围内的View被移出可视范围内时,其也会被添加到回收池中。以这种方式ListView只需占用非常少的内存几可以存储可视范围内的View和回收池中的View。
参数convertView实际上就是一个可回收的View。当ListView要回收这个View的时候,它的数据就会被清空。因此,当convertView不为null的时候,只需要将数据填充到里面,而不用Inflate一个新的View,这样可以优化性能。因为,Layout的Inflate是消耗资源巨大的代码,因为Infalte操作需要彻底包含整个XML代码树,而且还要实例化相应的View。
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.your_layout, null);
}
TextView text = (TextView) convertView.findViewById(R.id.text);
text.setText("Position " + position);
return convertView;
}
2.使用ViewHolder
ViewHolder就是用来存储那些在你的getView()方法中调用findViewById()方法得到的View。以这种方式,你只需要在第一次创建Item的时候调用findViewById就可以了。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.your_layout, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = convertView.getTag();
}
holder.text.setText("Position " + position);
return convertView;
}
private static class ViewHolder {
public TextView text;
}
3.异步加载
加载图片是一个比较耗时的操作,当用户快速滑动列表时,会频繁地 getView ,而 getView 是在主线程中被调用的,如果你在 getView 方法中直接加载 Image 或做其他耗时操作,就会造成滑动比较卡,解决方法是使用异步加载。
-
ListView加载图片乱序问题的解决方法:
-
getView中setTag,可以是图片的url等唯一标识
-
异步加载后,为ImageView设置图片之前,用findVIewWithTag查找tag是不是为null,不是null才设置图片
-
其他优化方法:
-
adapter的getView方法中尽可能的减少耗时的操作,getView方法执行的时间只有很短,否则会卡顿。
-
数据分页分批次加载
-
快速滑动时不要加载图片,否则会卡顿,如果在滑动时对滑动过的每张图片都要加载,会比较占内存。设置滚动监听,滚动的时候不要加载图片。
-
尽可能减少ListView的Item的Layout层次(如可以使用RelativeLayout替换LinearLayout,或使用自定的View代替组合嵌套使用的Layout)
-
onClickListener
,当ListView的item中有比如button这些子view时,需要对其设置onclickListener,通常的写法是在getView方法中一个个设置,比如holder.img.setonClickListener(new onClickListenr)...
但是这种写法每次调用getView时都设置了一个新的onClick事件,都需要new 监听器,效率很低。高效的写法可以直接在ViewHolder中设置一个position,然后viewHolder implements OnClickListenr:
class ViewHolder implements OnClickListener{ int position; TextView name; public void setPosition(int position){ this.position = position; } @Override public void onClick(View v) { switch (v.getId()){ //XXXX } } } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = inflater.inflate(R.layout.list_item, parent, false); holder = new ViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name); holder.name.setOnClickListener(holder); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } //设置holder holder.name.setText(list.get(position).partname); //设置position holder.setPosition(position); return convertView; }
参考:
https://blog.csdn.net/u014657752/article/details/47379941
https://www.zhihu.com/question/19703384
https://blog.csdn.net/guolin_blog/article/details/45586553