2016年5月25日修改:之前有朋友留言说是报nullPoint异常,问题确实存在。因最近工作忙,一直没有来得及改。
今天在工作中正好用这个万能工具类,所以把代码简单改了下。多谢朋友指正!
List,View,GridView等列表展示控件是我们在项目中不可或缺的一部分,而且在项目中
用到的地方肯定不止一两个地方,好的项目,大的项目可能要用到几十上百个ListView。
我们知道要实现ListView加载数据,就需要给ListView写数据适配器Adapter,
通常我们是根据需求,为不同的ListView为不同的Adapter,这个Adapter需要extends
BaseAdapter,这种 常规写法对我们来说轻车熟路,但是我们真要为项目中几十上百个
ListView写几十上面个Adapter extend BaseAdapter吗?那我们肯定不加班熬死
也累死了。我们项目中通常会写一个通用的CommonAdapter,然后在我们每一个ListView
中写一个Adapter extends CommonAdapter来减少代码。这几天项目发版本,bug不多,
又学习了下大神们讲的课程,今天我们就记录下实现一个通用的超级Adapter,释放我们的惰性。
优化ListView少不了ViewHolder,首先实现一个通用的ViewHolder
public class ViewHolder {
/**
* SparseArray是android里为<Interger,Object>这样的HashMap<Integer,Oject>
* 而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。
* 在Android中,当我们需要定义 HashMap<Integer, E> hashMap =
* new HashMap<Integer, E>()时我们可以使用如下的方式来取得更好的性能.
* SparseArray<E> sparseArray = new SparseArray<E>();
*/
private SparseArray<View> mViews;
private int mPosition;// 这个参数在我们防止数据错乱加载时可用到
private View mConvertView;
private Context mContext;
public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mPosition = position;
this.mContext = context;
mViews = new SparseArray<>();
mConvertView = LayoutInflater.from(mContext).inflate(layoutId, parent, false);
mConvertView.setTag(this);
}
/**
* 获取到ViewHolder
*
* @description:
* @author ldm
* @date 2015-10-13 上午10:08:41
*/
public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(context, parent, layoutId, position);
} else {
ViewHolder hoder = (ViewHolder) convertView.getTag();
hoder.mPosition = position;
return hoder;
}
}
public View getConvertView() {
return mConvertView;
}
/**
* 通过id获取控件
*
* @description:
* @author ldm
* @date 2015-10-12 下午8:01:46
*/
public <T extends View> T getViewById(int resId) {
View view = mViews.get(resId);
if (view == null) {
view = mConvertView.findViewById(resId);
mViews.put(resId, view);
}
return (T) view;
}
/**
* 设置TextView数据
*
* @description:
* @author ldm
* @date 2015-10-13 上午9:32:49
*/
public ViewHolder setTextView(int resId, String text) {
TextView tv = getViewById(resId);
tv.setText(text);
return this;
}
public ViewHolder setTextView(int resId, int textId) {
TextView tv = getViewById(resId);
tv.setText(textId);
return this;
}
/**
* 为ImageView设置数据
*
* @description:
* @author ldm
* @date 2015-10-13 上午9:34:14
*/
public ViewHolder setImageView(int resId, int picId) {
ImageView iv = getViewById(resId);
iv.setImageResource(picId);
return this;
}
// 可以根据自己需要写其它的组件
}
写一个通用的CommonAdapter与ViewHolder结合起来
/**
* 通用Adapter,我们为ListView写的数据适配adapter需要继承这个类
* @description:
* @author ldm
* @date 2015-10-13 上午10:12:05
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
protected Context mContext;
protected List<T> mDatas;
protected LayoutInflater mInflater;
protected int itemResId;
public CommonAdapter(Context mContext, List<T> mDatas, int itemResId) {
this.mContext = mContext;
this.mDatas = mDatas;
this.itemResId = itemResId;
mInflater = LayoutInflater.from(mContext);
}
@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 holder = ViewHolder.getHolder(mContext, convertView, parent, itemResId, position);
convert(holder, getItem(position));
return holder.getConvertView();
}
/**
* 数据处理方法,我们写的ListView对应adapter主要是实现这个方法功能
* @description:
* @author ldm
* @date 2015-10-13 上午10:13:06
*/
public abstract void convert(ViewHolder holder, T t);
}
当我们要使用的时候 ,定义好数据 实体类TestBean
// 我们为ListView写的adapter就只需要实现 下面这么几行代码
public class MyAdapter extends CommonAdapter<TestBean> {
public MyAdapter(Context mContext, List<TestBean> mDatas, int resId) {
super(mContext, mDatas, resId);
}
@Override
public void convert(ViewHolder holder, TestBean bean) {
holder.setTextView(R.id.item_name, t.getTitle());// 为item中的TextView设置数据
holder.setImageView(R.id.item_desc, R.drawable.ic_launcher);// 为item中的ImageView设置数据
}
}
在Activity中使用到的代码
private void initViews() {
this.mListView = (ListView) findViewById(R.id.test_lv);
mAdapter=new MyAdapter(this,mDatas,R.layout.listview_item);
this.mListView.setAdapter(mAdapter);
}