1、刚完成一个小项目,项目中有多个页面,其中包含了许多ListView和GridView,避免不了要写很多的Adapter,当时就像那么多重复的代码,若是抽取一下就好了,由于时间紧迫,没有来得及抽取,刚好前几天看到慕课上《打造万能适配器》,本文算是对该视频的学习记录,按照自己的方式,对视频中的代码进行了稍稍的改动,废话说多了,下面进入主题…
2、Demo源码:http://download.csdn.net/detail/gonghao2014/9704384
注:这里只给出关键部分代码
//类似ListView这样的视图,继承BaseAdapter实现ListView的适配器类
public class ListViewAdapter extends BaseAdapter {
private Context mContext;
private List<Bean> mBeans;
public ListViewAdapter(Context context, List<Bean> beans) {
this.mContext = context;
this.mBeans = beans;
}
@Override
public int getCount() {
return mBeans.size();
}
@Override
public Object getItem(int position) {
return mBeans.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item_grid_view, parent, false);
}
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
if (viewHolder == null) {
viewHolder = new ViewHolder();
convertView.setTag(viewHolder);
}
viewHolder.img = (ImageView) convertView.findViewById(R.id.id_img);
viewHolder.title = (TextView) convertView.findViewById(R.id.id_title);
Bean bean = mBeans.get(position);
viewHolder.img.setImageResource(bean.getImgId());
viewHolder.title.setText(bean.getTitle());
return convertView;
}
class ViewHolder {
ImageView img;
TextView title;
}
}
//当一个项目中类似这样的ListView和GridView多了以后,会发现要写很多个Adapter类,并且代码很多是重复的
//比如说:Context字段、List<Bean>实体数据字段、构造方法、getCount()、getItem()、getItemId()
1、仔细观察后发现,其实每个Adapter类中,最大的不同点就是用户看到的视图(childView),和视图中填充的数据
2、所以就想,能抽象一个转化方法–convert(视图Id,该视图的显示数据)
3、两个参数:视图Id(viewId)和该视图要显示的数据(bean.getXX())
4、写一个抽象类CommonAdapter,让需要使用的Adapter继承CommonAdapter类,重写其中的convert方法即可
第一步:新建一个CommonAdapter类,代码如下
/**
* 通用适配器类
* @author HaoG
* @param <T>
* 要填充的数据类型
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
private Context mContext; //上下文对象,LayoutInflater加载布局时用到
private List<T> mBeans; //视图要显示的数据的集合
private int mLayoutId; //要显示的视图所在的布局的ID
public CommonAdapter(Context context, List<T> beans, int layoutId) {
this.mContext = context;
this.mBeans = beans;
this.mLayoutId = layoutId;
}
@Override
public int getCount() {
return mBeans.size();
}
@Override
public Object getItem(int position) {
return mBeans.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(mLayoutId,
parent, false);
}
//这里是一个转换器类,下面详细介绍
Convertor convertor = Convertor.get(convertView);
//根据上面的想法,抽取出来的抽象方法convert()
convert(convertor, mBeans.get(position));
return convertView;
}
/**
* 使用转换器convertor,将数据bean显示在相对应View上
* 具体的视图和数据的适配依据需求而定,所以具体的实现要交个子类去实现
* @param convertor
* @param bean
*/
public abstract void convert(Convertor convertor, T bean);
}
第二步:新建一个Convertor类,代码如下
/**
* 转换器类 封装了一个ViewHolder(即mViews)
*
* @author HaoG
*/
public class Convertor {
private View mConvertView;
private SparseArray<View> mViews;// viewHolder
public Convertor(View convertView) {
mViews = new SparseArray<View>();
this.mConvertView = convertView;
}
/**
* 获取convertor实例
*
* @param convertView
* @return
*/
public static Convertor get(View convertView) {
Convertor convertor = (Convertor) convertView.getTag();
if (convertor == null) {
convertor = new Convertor(convertView);
convertView.setTag(convertor);
}
return convertor;
}
/**
* 根据viewId获取View视图实例
*
* @param viewId
* @return
*/
@SuppressWarnings("unchecked")
private <T extends View> T getView(int viewId) {
View childView = mViews.get(viewId);
if (childView == null) {
childView = mConvertView.findViewById(viewId);
mViews.put(viewId, childView);
}
return (T) childView;
}
/**
* 给指定viewId的TextView控件设置文本
*
* @param viewId
* @param text
* @return
*/
public Convertor setText(int viewId, String text) {
TextView tv = getView(viewId);
tv.setText(text);
//返回值是Convertor类的对象本身是为了代码的书写方便,可以链式书写,下面可以看到链式书写形式
return this;
}
/**
* 给指定viewId的ImageView控件设置图片
*
* @param viewId
* @param imgId
* @return
*/
public Convertor setImageResource(int viewId, int resId) {
ImageView iv = getView(viewId);
iv.setImageResource(resId);
return this;
}
// PS:
// 类似setText(),setImageResource()方法,可根据需求自行添加
// 如Item视图中含有RadioButton控件,那个可以添加setChecked()方法
}
第三步:根据业务需求,新建一个CommonAdapter的子类–ListViewAdapter类,代码如下
/**
* ListView适配器类
*
* @author HaoG
*
*/
public class ListViewAdapter3 extends CommonAdapter<ListBean> {
public ListViewAdapter3(Context context, List<ListBean> beans, int layoutId) {
super(context, beans, layoutId);
}
/**
* 1、在这里我们可以看到子类中只需要实现其convert()方法即可
* 2、在Convertor类中,已经封装的相关的接口,在这里直接调用即可
*/
@Override
public void convert(Convertor convertor, ListBean bean) {
convertor.setImageResource(R.id.id_img, bean.getImgId())
.setText(R.id.id_title, bean.getTitle());
}
}
1、到这里基本就结束了,如果有不太懂的地方,可以去慕课,观看《打造Android万能适配器》
2、这里并不是打广告,我也是Android初学者,在写项目时多个Adapter感到繁琐,刚好碰到这个通用的CommonAdapter,便记录下学习小结,愿与君共进步…
3、感谢《慕课网–打造万能适配器》