自定义Listview适配器的优化
【以下两段只是我自己的理解,要是表达不清,可跳过看后面的】
介绍:Listview控件一直是我们在android项目开发中经常需要用到的。对于刚接触listview的我,在写listview时候都用的自己自定义的listview,这样可以随意的控制我们的listview item。创建过程一般是先写个item类用来管理每个item的组件值,然后就是写一个xml页面,设计listview item每个组件的摆放位置,接着就是自定义一个类继承BaseAdapter,创建一个构造方法,重写下他的4个方法,并在getview()方法去设置每个item的值。最后在调用listview.setAdapter()方法。这样一个自定义ListView就写好了。
优化:按以上方法确实ListView就创建好了,并能正常运行程序,但是大家有没有想过我们自定义适配器中重写的getview()方法在我们程序运行的时候到底要运行多少次,毕竟我们手机屏幕有限,不可能把所有的listview条目都显示出来,那么是不是表示我们每次加载新的item都要调用呢,答案是肯定的,每次新加载出一个新的item都要调用一次getview()方法。而我们注意到,每次执行getview()方法,那么就会重复调用findViewById()方法,后面就不用说了,这是需要优化的地方之一。第二其实是也是getView()方法的一个参数convertView,细心的人会发现其实convertView就是我们需要加载的这个item,可是我们知道listview中每个item的布局都是一样的,所以这里的convertView也是一样的,那么我们能不能在只需要加载一个convertView,然后后面item都用这个convertView,这里我先给出答案,是可以的,但是不是加载一个,是加载一个屏幕所能容纳的item个数,能不能想明白,话说我也有点晕,不过想想应该就是这样的。
优化点:(专业术语)
1:重用了convertView,很大程度上的减少了内存的消耗
解决方法:先判断convertView是否为空,若为空则先获取再调用,否则可直接调用。
2:上面的写法会有一个缺点,就是每次在getVIew的时候,都需要重新的findViewById,重新找到控件,然后进行控件的赋值以及事件相应设置。
解决方法:通常有一个内部类class ViewHolder,这个ViewHolder,用来标识view中一些控件,方便进行一些事件相应操作的设置
设置ViewHolder为static,也就是静态的,静态类只会在第一次加载时会耗费比较长时间,但是后面就可以很好帮助加载,同时保证了内存中只有一个ViewHolder,节省了内存的开销
View中的setTag(Onbject)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。
设置ViewHolder为static,也就是静态的,静态类只会在第一次加载时会耗费比较长时间,但是后面就可以很好帮助加载,同时保证了内存中只有一个ViewHolder,节省了内存的开销
View中的setTag(Onbject)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。
代码参考:
public class GeneralAdapter extends BaseAdapter {
private List<Data>mDatas;
private LayoutInflater mInflater;
private Context mContext;
public GeneralAdapter(List<Data> mDatas, Context mContext) {
super();
this.mDatas = mDatas;
this.mContext = mContext;
this.mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mDatas.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view;
MyHolder myHolder;
Data data;
if(convertView==null){
view = mInflater.inflate(R.layout.listview_common_item, parent,false);
myHolder = new MyHolder();
myHolder.imageView = (ImageView)view.findViewById(R.id.iv);
myHolder.textView = (TextView)view.findViewById(R.id.tv);
view.setTag(myHolder);
}else{
view = convertView;
}
data = mDatas.get(position);
myHolder = (MyHolder) view.getTag();
myHolder.imageView.setImageResource(data.getId());
myHolder.textView.setText(data.getContent());
return view;
}
static class MyHolder{
ImageView imageView;
TextView textView;
}
}