在开发Android应用的时候会常用到扩展的BaseAdapter来实例Adapter,通过getCount()方法来控制显示item的数量,用过getView()方法来返回每个item显示的数据的view。每显示一个item,getView()方法就会执行一次,因此getView()方法的执行效率十分关键,在显示的item十分庞大时,如果getView()方法执行速度慢,势必带来的问题就是手机滑动的十分的卡,用户体验十分的差。再以用户体验为重要指标的开发中,这种情况是不允许的,这就要求对getView()方法进行优化。
在扩展BaseAdapter的时候,如何解析出item对应的布局和找到相对应的控件是十分重要的。而找到item并在java代码中实例化的方法第一个想到的肯定就是View类的inflate()这个静态方法,但是这个方法实际上是十分消耗时间的。如果每次执行getView()方法都去执行这个方法,想想就知道是不可靠的。
那么如何解决这一麻烦呢,其实不用你自己费脑子想,API开发人员早就想到了这一问题。那么我们来看看他们是如何解决这一问题的吧:
我们再来看看getView()这个方法,它是这样的:
@Override
public View getView(int position, View convertView, ViewGroup parent){}
他有三个参数,存放item的convertView
posotion:当前item的位置position
convertView:存放item的View对象
parent:item的父容器
我们来重点看第二个参数converView,这就是解决上述inflate方法的精髓所在,上面已经说到inflate方法十分耗时,但它解析出来的对象对于每一个item都是相同的,也就是说每个item的布局都是一样的。从这点出发,能不能把item的布局的对象保存起来呢?convertView就是这样一个作用,下面是它的工作原理:
从图中可以看出一下几点信息:
1、只有可见的item存在于内存中
2、当有item滚出屏幕,并且有一个新的item滚上来(可见)时,convertView从null变为item1。
这种机制在生成视图时减少了大量的视图创建,省去了大量创建视图时的消耗。根据以上机制,在convertView不为空之后,就可以直接通过convertView创建视图。一下时代码实现:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView =View.inflate(context, R.layout.item, null);
}
ImageView imageView =
(ImageView)convertView.findViewById(R.id.item_iv);
imageView.setImageResource(R.drawable.ic_launcher);
return convertView;
}
上面我们解决了一个inflate方法耗时的问题,其实还有一个方法也很耗时,那就是findViewById这个方法。同样的,每个item需要的控件都是来自于一个布局文件,也是相同的,这就诱使我们又想到了相同的方法——将找到的控件保存起来。如何保存呢,我们可以通过创建一个静态内部类ViewHolder来保存这几个控件,后面的item直接从ViewHolder中取出来使用就可以了。下面是完整的扩展BaseAdapter类MyAdapter的代码:
public class MyAdapter extends BaseAdapter{
private Context context;
private List<Bean> list;
public MyAdapter(Context context,List<Bean> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView==null){
viewHolder = new ViewHolder();
convertView = View.inflate(context, R.layout.item, null);
viewHolder.icon_iv =
(ImageView) convertView.findViewById(R.id.item_iv);
viewHolder.name_tv =
(TextView) convertView.findViewById(R.id.item_name);
viewHolder.desc_tv =
(TextView) convertView.findViewById(R.id.item_desc);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.desc_tv.setText(list.get(position).getDesc_tv());
viewHolder.icon_iv.setImageResource(list.get(position).getIcon_iv());
viewHolder.name_tv.setText(list.get(position).getName_tv());
return convertView;
}
static class ViewHolder{
ImageView icon_iv;
TextView name_tv;
TextView desc_tv;
}
}