1.通用的ViewHolder
首先分析下ViewHolder的作用,通过convertView.setTag与convertView进行绑定,然后当convertView复用时,直接从与之对于的ViewHolder(getTag)中拿到convertView布局中的控件,省去了findViewById的时间~
也就是说,实际上们每个convertView会绑定一个ViewHolder对象,这个viewHolder主要用于帮convertView存储布局中的控件。
那么我们只要写出一个通用的ViewHolder,然后对于任意的convertView,提供一个对象让其setTag即可;
既然是通用,那么我们这个ViewHolder就不可能含有各种控件的成员变量了,因为每个Item的布局是不同的,最好的方式是什么呢?
提供一个容器,专门存每个Item布局中的所有控件,而且还要能够查找出来;既然需要查找,那么ListView肯定是不行了,需要一个键值对进行保存,键为控件的Id,值为控件的引用,相信大家立刻就能想到Map;但是我们不用Map,因为有更好的替代类,就是我们android提供的SparseArray这个类,和Map类似,但是比Map效率,不过键只能为Integer.
下面看我们的ViewHolder类:
public class ViewHolder {
private SparseArray<View> mViews;
private int mPosition;
private View mConvertView;
public ViewHolder(Context context, ViewGroup parent, int layoutId,
int position) {
this.mPosition = position;
this.mViews = new SparseArray<>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
mConvertView.setTag(this);
}
public static ViewHolder get(Context context, View convertView, ViewGroup parent,
int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(context, parent, layoutId, position);
} else {
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
viewHolder.mPosition = position;
return viewHolder;
}
}
/**
* 通过viewId获取控件
*
* @param viewId
* @param <T>
* @return
*/
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
/**
* 为TextView设置字符串
*
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
public ViewHolder setImageResource(int viewId, int drawableId) {
ImageView view = getView(viewId);
view.setImageResource(drawableId);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param bitmap
* @return
*/
public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param url
* @return
*/
public ViewHolder setImageByUrl(int viewId, String url) {
// ImageLoader.getInstance(3, Type.LIFO).loadImage(url,
// (ImageView) getView(viewId));
return this;
}
public int getPosition() {
return mPosition;
}
}
2、打造通用的Adapter
下面看如何打造一个通过的Adapter,我们叫做CommonAdapter
继续分析,Adapter一般需要保持一个List对象,存储一个Bean的集合,不同的ListView,Bean肯定是不同的,这个CommonAdapter肯定需要支持泛型,内部维持一个List<T>,就解决我们的问题了;
于是我们初步打造我们的CommonAdapter
public abstract class CommonAdapter<T> extends BaseAdapter {
protected Context mContext;
protected LayoutInflater mInflater;
protected List<T> mDatas;
protected int layoutId;
public CommonAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
this.mDatas = datas;
this.layoutId = layoutId;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public T getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent,
layoutId, position);
convert(viewHolder, getItem(position));
return viewHolder.getConvertView();
}
public abstract void convert(ViewHolder viewHolder, T t);
}