打造万能Viewholder,告别重复代码
2016-05-11 12:03
204 查看
每次写ListView显示列表都会重复写出if(convertview == null){}else{} 这些重复的代码,既然是重复的,肯定是可以提取复用的。。。
开始咯:
首先CommonAdapter类继承BaseAdapter并实现其方法,因为我们要做到灵活性,所以实体类,item布局都是要传进来的
public CommonAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.mDatas = datas;
this.layoutId = layoutId;
}
实现的BaseAdapter的类:
@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) {
return null;
}
因为我们要使用ViewHolder来进行复用,所以开始编写ViewHolder类:
传统模式需要使用convertView.setTag(holder)将holder和adapter结合起来,所以我们现在需要将各种控件存储起来,然后再需要使用的地方取出这个控件进行使用就好了,在这里推荐使用SparseArray,实际上它内部也是维护的一个map集合,但是它比HaseMap效率要更高,可以看下官方解释
SparseArrays map integers to Objects. Unlike a normal array of Objects,there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure
doesn't rely on an extra entry object for each mapping.
private SparseArray<View> mViews;
我们可以开始编写一个ViewHolder的入口来供Adapter中的getView()方法调用
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 holder = (ViewHolder) convertView.getTag();
holder.mPosition = position;
return holder;
}
}
还是和传统模式的复用convertView一样的,当convertView不为空的时候,还是使用getTag(),当为空的时候通过使用new ViewHolder来进行初始化操作
public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mPosition = position;
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
mConvertView.setTag(this);
}
ViewHolder里面传入我们需要的参数,当然包括item布局文件
有了这样一个ViewHolder类之后,并且提供了调用入口,这时候我们就可以在BaseAdapter中的getView()中进行调用了
@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();
}
这里返回的是Viewholder中的getConvertView()
public View getConvertView() {
return mConvertView;
}
getView中我们对外提供了一个抽象方法convert()来供调用,返回了holder和我们的实体
public abstract void convert(ViewHolder holder, T t);
好了,CommonAdapter中基本就需要这些东西了
现在回到我们的ViewHolder类中,要使用ViewHolder,所以我们要怎么获取到控件呢
上面有讲到过,使用SparseArray来存储View控件
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;
}
和HashMap一样,通过key来获取value,如果没有就使用convertView来findViewById()来获取控件,再添加到集合里并返回
到此我们的ViewHolder就已经编写差不多了
那如何使用呢?
CommonAdapter<MenuEntity> adapter = new CommonAdapter<MenuEntity>(context,menus,R.layout.item_list) {
@Override
public void convert(ViewHolder holder, MenuEntity menuEntity) {
TextView tv = holder.getView(R.id.tv);
tv_kind_name.setText(menuEntity.name);
}
};
可以直接在MainActivity中使用内部类来实现重写convert(),当然也可以重新新建一个类来继承我们的CommonAdapter,然后实现里面的方法咯
为了更简洁,我们还可以做如下优化:
/**
* 设置TextView的值
*
* @param viewId
* @param value
* @return
*/
public ViewHolder setText(int viewId, String value) {
TextView textView = getView(viewId);
textView.setText(value);
return this;
}
public ViewHolder setImageResource(int viewId, int resId) {
ImageView view = getView(viewId);
view.setImageResource(resId);
return this;
}
public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
我们可以直接在ViewHolder类中添加如是方法,获取控件并设置值,这个时候我们的convert中就可以变成这样:
CommonAdapter<MenuEntity> adapter = new CommonAdapter<MenuEntity>(context,menus,R.layout.item_gamelist_kind_list) {
@Override
public void convert(ViewHolder holder, MenuEntity menuEntity) {
holder.setText(R.id.tv_kind_name,menuEntity.menuName);
}
};
并且还可以连" . " 哦~
好了 至此我们的类已经全部编写完成,以后我们每次要使用BaseAdapter的时候就只需要new CommonAdapter就好了,是不是很简洁 @@
附上Utils源码连接:http://download.csdn.net/detail/flyingzhlunasea/9516487
欢迎指正!!!
开始咯:
首先CommonAdapter类继承BaseAdapter并实现其方法,因为我们要做到灵活性,所以实体类,item布局都是要传进来的
public CommonAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
this.mDatas = datas;
this.layoutId = layoutId;
}
实现的BaseAdapter的类:
@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) {
return null;
}
因为我们要使用ViewHolder来进行复用,所以开始编写ViewHolder类:
传统模式需要使用convertView.setTag(holder)将holder和adapter结合起来,所以我们现在需要将各种控件存储起来,然后再需要使用的地方取出这个控件进行使用就好了,在这里推荐使用SparseArray,实际上它内部也是维护的一个map集合,但是它比HaseMap效率要更高,可以看下官方解释
SparseArrays map integers to Objects. Unlike a normal array of Objects,there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure
doesn't rely on an extra entry object for each mapping.
private SparseArray<View> mViews;
我们可以开始编写一个ViewHolder的入口来供Adapter中的getView()方法调用
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 holder = (ViewHolder) convertView.getTag();
holder.mPosition = position;
return holder;
}
}
还是和传统模式的复用convertView一样的,当convertView不为空的时候,还是使用getTag(),当为空的时候通过使用new ViewHolder来进行初始化操作
public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mPosition = position;
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
mConvertView.setTag(this);
}
ViewHolder里面传入我们需要的参数,当然包括item布局文件
有了这样一个ViewHolder类之后,并且提供了调用入口,这时候我们就可以在BaseAdapter中的getView()中进行调用了
@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();
}
这里返回的是Viewholder中的getConvertView()
public View getConvertView() {
return mConvertView;
}
getView中我们对外提供了一个抽象方法convert()来供调用,返回了holder和我们的实体
public abstract void convert(ViewHolder holder, T t);
好了,CommonAdapter中基本就需要这些东西了
现在回到我们的ViewHolder类中,要使用ViewHolder,所以我们要怎么获取到控件呢
上面有讲到过,使用SparseArray来存储View控件
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;
}
和HashMap一样,通过key来获取value,如果没有就使用convertView来findViewById()来获取控件,再添加到集合里并返回
到此我们的ViewHolder就已经编写差不多了
那如何使用呢?
CommonAdapter<MenuEntity> adapter = new CommonAdapter<MenuEntity>(context,menus,R.layout.item_list) {
@Override
public void convert(ViewHolder holder, MenuEntity menuEntity) {
TextView tv = holder.getView(R.id.tv);
tv_kind_name.setText(menuEntity.name);
}
};
可以直接在MainActivity中使用内部类来实现重写convert(),当然也可以重新新建一个类来继承我们的CommonAdapter,然后实现里面的方法咯
为了更简洁,我们还可以做如下优化:
/**
* 设置TextView的值
*
* @param viewId
* @param value
* @return
*/
public ViewHolder setText(int viewId, String value) {
TextView textView = getView(viewId);
textView.setText(value);
return this;
}
public ViewHolder setImageResource(int viewId, int resId) {
ImageView view = getView(viewId);
view.setImageResource(resId);
return this;
}
public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
我们可以直接在ViewHolder类中添加如是方法,获取控件并设置值,这个时候我们的convert中就可以变成这样:
CommonAdapter<MenuEntity> adapter = new CommonAdapter<MenuEntity>(context,menus,R.layout.item_gamelist_kind_list) {
@Override
public void convert(ViewHolder holder, MenuEntity menuEntity) {
holder.setText(R.id.tv_kind_name,menuEntity.menuName);
}
};
并且还可以连" . " 哦~
好了 至此我们的类已经全部编写完成,以后我们每次要使用BaseAdapter的时候就只需要new CommonAdapter就好了,是不是很简洁 @@
附上Utils源码连接:http://download.csdn.net/detail/flyingzhlunasea/9516487
欢迎指正!!!
相关文章推荐
- spring基础部分——注解
- 详解ASP.NET验证码的生成方法
- PHP数据库操作Helper类完整实例
- spring线程池ThreadPoolExecutor配置并且得到任务执行的结果
- C#制作、打包、签名、发布Activex全过程【转】
- java.lang.OutOfMemoryError: PermGen space
- Yii创建模板
- python 多行匹配
- Spring中的ThreadPoolTaskExecutor
- Spring MVC工作流程图
- 设置eclipse 黑色主题
- java注解(二)Annotation使用案例
- Python的functools模块
- 实例解析Java设计模式编程中的适配器模式使用
- python self introspection
- 【C++】reference parameter-引用参数
- C# Form内存回收
- 二叉树的链表表示 C++实现
- C++Primer::头文件设计基本原则 与 预处理器介绍
- Eclipse安装及其配置方法