动手前先讲一下为什么要用这个ViewHolder,不用这个也可以实现啊,感觉鸡肋有木有,可是实际上呢,既然发明肯定有存在的必要性,接下来就来简单讲一下BaseAdapter,慢慢就能理解为什么需要用ViewHolder来优化了!!!
当用到像ListView、Spinner、Gallery及GridView等UI显示组件时,自然需要用到数据适配器 Adapter 这个东西
<pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'宋体';font-size:9.0pt;"><span style="color:#cc7832;"></span>
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
* Created by HD on 2016/3/9.
*/
public class MyAdapter extends BaseAdapter {
private List<ItemBean> mList;
private LayoutInflater mInflater;
public MyAdapter(Context context, List<ItemBean> list) {
this.mList = list;
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
<span style="white-space:pre"> </span>return null;
}
}
因为这是讲ViewHolder优化的,所以继承BaseAapter这个基础类而得到的具体几个方法就不细写了。
接下来介绍第一钟方式,也是最笨的,根本没有用到ListView控件的缓存机制。
public View getView( int position, View convertView, ViewGroup parent )
{
View v = mInflater.inflate( R.layout.item, null );
ImageView imageView = (ImageView) v.findViewById( R.id.iv_image );
TextView titleView = (TextView) v.findViewById( R.id.tv_title );
TextView contentView = (TextView) v.findViewById( R.id.tv_content );
ItemBean bean = mList.get( position );
imageView.setImageResource( bean.getItemImageResid() );
titleView.setText( bean.getItemtitle() );
contentView.setText( bean.getItemContent() );
return(v);
}
通过LayoutInflater对象的inflate方法找到对应的模块,根据id找到模块,传入数据,返回View,这是最基本的。但是也是最笨的,连缓存机制都没有应用到。
第二种方式,还算是比较正常的,因为已经利用到ListView的缓存机制。
public View getView( int position, View convertView, ViewGroup parent )
{
if ( convertView == null )
{
convertView = mInflater.inflate( R.layout.item, null );
}
ImageView imageView = (ImageView) convertView.findViewById( R.id.iv_image );
TextView titleView = (TextView) convertView.findViewById( R.id.tv_title );
TextView contentView = (TextView) convertView.findViewById( R.id.tv_content );
ItemBean bean = mList.get( position );
imageView.setImageResource( bean.getItemImageResid() );
titleView.setText( bean.getItemtitle() );
contentView.setText( bean.getItemContent() );
return(convertView);
}
当一个ItemView滚出界面的时候,他并没有消失,而是储存在converView里面了,这时候就可以检测这是不是null,是null就新建一个,不是就可以直接用以前储存在converView里的,从新给itemView传入数据,再次显示,这就是循环使用View,不必一直新建视图。
第三种方式就是在第二种方式上优化产生的,因为第二种方式在使用上,每一次循环利用VIew,需要传入数据时,都是用findView()再次寻找控件,item比较少的时候,这样一次次的寻找消耗的时间还可以接受,但是当item达到上千上万乃至更多的时候,就能累加的很明显的时间,给用户造成很不好的用户体验。这时候就用到ViewHolder来优化。
public View getView( int position, View convertView, ViewGroup parent )
{
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.iv_image);
viewHolder.titleView = (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.contentView = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
ItemBean bean = mList.get(position);
viewHolder.imageView.setImageResource(bean.getItemImageResid());
viewHolder.titleView.setText(bean.getItemtitle());
viewHolder.contentView.setText(bean.getItemContent());
return convertView;
}
}
class ViewHolder {
public ImageView imageView;
public TextView titleView;
public TextView contentView;
}
先创建一个内部类ViewHolder,根据你的Item里有多少控件设立多少属性,如果converView为null,就new对象,根据对象的传入值,只findViewById()一次,然后把信息添加到Tag里,如果不为空,就用上次的VIew,直接获取Tag里面的信息进行操作,然后返回converView即可。这样的效果是可以不用每一次都findViewById(),优化了资源。