前言
在一个项目里,如果ListView是经常用到的,我们可以选择对ListView进行封装,封装过后的ListView,在写Adapter的时候,可以省事很多.下面记录没有封装之前的ListView写法,和封装之后的写法.
没有封装之前的ListView
class HomeAdapter extends Base adapter{
@Override
public int getCount() {
return data.size();
}
@Override
public object getItem(int position) {
return data.get(position);
}
@Override
public int getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
//1.加载布局文件
convertView = UIUtils.inflate(R.layout.list_item_home);
//2.初始化控件
holder.tv_content = (TextView) convertView.findViewById(R.id.tv_content);
//3.打标记
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//4.根据数据刷新页面
holder.tv_content.setText(getItem(position));
return convertView;
}
}
class ViewHolder {
TextView tv_content;
}
从上面的一般写法中,我们可以看到,getCount(),getItem(int position),getItemId(int position)的重写一般都是固定模式的.唯一需要根据具体项目来实现的就是getView()方法,而getView方法里面可以总结为一下四个步骤:
- 加载布局文件
- 初始化控件
- 打标记
- 根据数据,刷新界面
根据上述步骤,可以将getView方法也进行封装
封装思路:
将BaseAdapter封装成MyBaseAdapter
将ViewHolder封装成BaseHolder
让BaseHolder和MyBaseAdapter打交道
在用到ListView的时候直接创建一个对应的Holder即可.
下面记录详细步骤.
对BaseAdapteer进行封装
public abstract class MyBaseAdapter<T> extends BaseAdapter {
private ArrayList<T> data;
public MyBaseAdapter(ArrayList<T> data) {
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public T getItem(int position) {
return data.get(position);
}
@Override
public int getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
BaseHolder holder;
if (convertView == null) {
//1.加载布局文件
//2,初始化控件fvb
//3.打标记tag
holder = getHolder();
}else{
holder= (BaseHolder) convertView.getTag();
}
//4.设置数据刷新界面
holder.setData(getItem(position));
return holder.getRootView();
}
/**
*拿到holder的抽象方法,让子类实现
*@author zfy
*@created at 2016/7/20 17:03
*/
public abstract BaseHolder<T> getHolder();
}
借助构造方法,在外加将数据集合传入内部,然后借助泛型可以很快的写出封装后的的getCount(),getItem(int position),getItemId(int position)三个方法.这里不做赘述.
下面详细解释getView方法的封装:
[getView方法的封装需要结合ViewHolder的封装一起]
- 首先我们还是创建一个Holder,但是此处的Holder就是封装的BaseHolder;
- 然后还是判断convertView是否为空;
- 若为空,则在基类BaseHolder的getHolder()方法里完成前三个步骤;
- 若不为空,直接从tag里拿出;
- 步骤4是调用BaseHolder里的setData方法来实现的;
- 其中getHolder()是抽象方法,需要BaseHolder的子类来具体的实现;
- setData()方法里也有抽象方法refreshView()也是让子类来具体实现;
对ViewHolder进行封装
public abstract class BaseHolder<T> {
private View mRootView;
private T data;
//在构造方法中初始化布局
public BaseHolder() {
//1.加载布局文件
//2.在initView方法中初始化控件
mRootView = initView();
//3.打标记
mRootView.setTag(this);
}
//基类不知道具体的实现,需要子类去具体的实现
public abstract View initView();
//让外界拿到跟item布局mRootView的方法
public View getRootView() {
return mRootView;
}
//4.根据数据甩你界面的方法,由于基类不知道具体的实现,所以让子类完成
public abstract void refreshView(T data);
public void setData(T data) {
this.data = data;
refreshView(data);
}
public T getData() {
return data;
}
}
- 首先先一个抽象方法,initView(),这个方法暴露给子类,让子类在这个方法里面完成步骤1.2即:加载布局,初始化控件,这个方法返回的mRootView就是ListView的item的布局.然后将此方法写在BaseHolder的构造方法里面,只要一new BaseHolder或者其子类,该方法就会调用.
- 在构造方法里完成settag方法.
- getRootView()方法用于外界的getView方法返回item的view
- refreshView()抽象方法,是根据数据刷新界面的方法,也就是步骤4.
- setData()方法内部调用的也是refreshView方法.
封装之后的用法
结合一般的使用方法,现在使用封装的listView就简单了很多,先创建一个子类holder继承自BaseHolder,然后创建对应的子类adapter继承自MyBaseAdapter
将文章开始的一般写法改造之后如下:
- 创建一个HomeHolder
public class HomeHolder extends BaseHolder<String> {
private TextView tv_content;
@Override
public View initView() {
//1.加载布局
View view = UIUtils.inflate(R.layout.list_item_home);
//2.初始化控件
tv_content = (TextView) view.findViewById(R.id.tv_content);
//3.设置tag,在基类里面已经完成
return view;
}
//4.根据数据刷新界面
@Override
public void refreshView(String data) {
tv_content.setText(data);
}
}
2.重写HomeAdapter
class HomeAdapter extends MyBaseAdapter<String> {
public HomeAdapter(ArrayList<String> data) {
super(data);
}
@Override
public BaseHolder<String> getHolder() {
return new HomeHolder();
}
}
前后对比一下,是不是简化了很多呢!
如果项目中所用到ListView不多,那么没有必要对Adapter进行封装,太费劲.但是在ListView很多的情况下,封装之后的代码可以大大提高我们的编码效率,更主要的是内部高内聚,外部低耦合这一理念,体现的淋漓尽致!
水平有限,难免出错