标签:
Adapter是数据和UI之间的一个桥梁,在listview,gridview等控件中都会使用到,android给我们提拱了4个adapte供我们使用:
在实际项目中往往用的最多的还是BaseAdapter,系统提供的几个adapter大多数只有在写demo才为了图省事去用一下而已,这在包建强的《app研发录》中的也有所体现,第一章介绍adapter时就提到要求所有adpater继承自BaseAdapter,从构造函数List<自定义实体>这样的数据集合,从而完成ListView的填充工作
,本篇主要总结一下BaseAdapter.
基本的一般只需要4步即可完成
- 继承
BaseAdapter
- 实现
getCount
、getItem
、getItemId
、getView
- 书写
ViewHolder
内部类去存储复用View- 在
getView
中实现数据的设置
下面给出一个基本的NormalAdapter实现的代码
public class NormalAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
private List<TestBean> datas;
//NormalAdapter需要一个Context,通过Context获得Layout.inflater,然后通过inflater加载item的布局
public NormalAdapter(Context context, List<TestBean> datas) {
layoutInflater = LayoutInflater.from(context);
this.datas = datas;
}
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.item_list, parent, false);
holder = new ViewHolder();
holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
holder.tv_des = (TextView) convertView.findViewById(R.id.tv_desc);
holder.tv_time = (TextView) convertView.findViewById(R.id.tv_time);
holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
//说明convertview已经被复用,已经设置过tag
holder = (ViewHolder) convertView.getTag();
}
TestBean testBean = datas.get(position);
holder.tv_title.setText(testBean.getTitle());
holder.tv_des.setText(testBean.getDesc());
holder.tv_time.setText(testBean.getTime());
holder.tv_name.setText(testBean.getName());
return convertView;
}
/**
* viewHoder服务于特定的Adapter,根据对应的item_layout书写
*/
private static class ViewHolder {
TextView tv_title;
TextView tv_des;
TextView tv_time;
TextView tv_name;
}
}
这样会带来一些问题,一个listview就要对应一个adpater,还要对应一个viewholder,这里有很多冗余的代码如getCount
、getItem
、getItemId
这些可以被抽象出来,其实封装的思路很简单,主要集中在getView
这个方法上,通过分析最普通的NormalAdapter可以看出,getView
主要完成三个部分
返回convertView
这三部分主要封装在BaseholderTool中
BaseAdapterTool
BaseAdapterTool比较简单就是继承BaseAdapter重写几种方法在getView中使用BaseViewHolderTool
关键代码如下
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//使用通用vierholder
BaseViewHolderTool holder = BaseViewHolderTool.get(context, convertView, parent, layoutId, position);
convert(holder, getItem(position));
return holder.getBaseConvertView();
}
/**
* 将该方法公布出去
*
* @param holder
* @param t
*/
public abstract void convert(BaseViewHolderTool holder, T t);
BaseviewHolderTool
SparseArray
public class BaseViewHolderTool {
private SparseArray<View> views;
private int basePosition;
private View baseConvertView;
public BaseViewHolderTool(Context context, ViewGroup parent, int layoutId, int position) {
this.basePosition = position;
this.views = new SparseArray<View>();
baseConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
baseConvertView.setTag(this);
}
/**
* 获得convertview不同情况的holder
*
* @param context
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static BaseViewHolderTool get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new BaseViewHolderTool(context, parent, layoutId, position);
} else {
BaseViewHolderTool holder = (BaseViewHolderTool) convertView.getTag();
holder.basePosition = position;//更新position位置
return holder;
}
}
/**
* 通过id获取控件
*
* @param viewId
* @param <T>
* @return
*/
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = baseConvertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
public View getBaseConvertView() {
return baseConvertView;
}
}
效果图如下:
这里要谈的是多个布局同时出现在一个listview中,
这时候就需要
重写 getViewTypeCount() – 返回你有多少个不同的布局
重写 getItemViewType(int) – 由position返回view type id
然后在getview中,
int viewType = getItemViewType(position);//获取对应的类型
这里做了一个简单地demo在偶数行显示item_list2,奇数行显示item_list
@Override
public int getItemViewType(int position) {
return position % 2 == 0 ? TYPE_SEPARATOR : TYPE_MAIN;
}
效果图如下
demo已经传到github上AdapterStudy
标签:
原文地址:http://blog.csdn.net/xsf50717/article/details/51042814