Android---封装ListView的Adapter

前言

在一个项目里,如果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方法里面可以总结为一下四个步骤:

  1. 加载布局文件
  2. 初始化控件
  3. 打标记
  4. 根据数据,刷新界面

根据上述步骤,可以将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

将文章开始的一般写法改造之后如下:

  1. 创建一个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很多的情况下,封装之后的代码可以大大提高我们的编码效率,更主要的是内部高内聚,外部低耦合这一理念,体现的淋漓尽致!

水平有限,难免出错

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值