ListView适配器的超省写法

原文 http://www.jianshu.com/p/cef7b2808335 

如果你是做 android 开发的一个组件是你一定会常常使用到的,没错就是 ListView,

对于 ListView 的使用,他有两个重点的部分,一个是下拉刷新和加载更多,这个今天我们不讲,另外一个是 BaseAdapter 的使用,这个是今天的主角,BaseAdapter 中又有 ViewHolder 模式来实现缓存视图
继承BaseAdapter类,实现以下几个方法

getCount() ->int 返回的是 List的个数
getView(int, View, ViewGroup)->View 返回显示的视图
getItemId(int position) ->long返回position位置的 id
getItem(int position)->Object 返回position位置的 item

现在我们在这个基础上,继承 BaseAdapter 实现几个方法.
MBaseAdapter.class

public abstract class MBaseAdapter  extends BaseAdapter {
    public LayoutInflater inflater;
    public Context context;
    public List<?> list;
    public MBaseAdapter(Context context, List<?> list) {
        this.context = context;
        this.list = list;
        this.inflater = LayoutInflater.from(context);
    }
    public MBaseAdapter(LayoutInflater inflater, List<?> list) {
        this.context = inflater.getContext();
        this.list = list;
        this.inflater = inflater;
    }
    @Override
    public int getCount() {
        return list.size();
    }
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return getView33(position, convertView, parent);
    }
    /**
     * 与BaseAdapter 中的getView() 一样
     *
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    public abstract View getView33(int position, View convertView,
                                   ViewGroup parent);
}

为了实现 ViewHodler 缓存我写了这个工具类
ViewHolderUtils.class

public class ViewHolderUtils {
    /**
     * 得到视图为 view 的 viewHodler
     * @param view
     * @return
     */
    public ViewHolder get(View view) {
        ViewHolder viewHolder = (ViewHolder) view.getTag();
        if (viewHolder == null) {
            viewHolder = new ViewHolder(view);
            view.setTag(viewHolder);
        }
        return viewHolder;
    }
    /**
     * viewhodler  存储 view的子 view 的索引
     * @author zzz40500
     *
     */
    public class ViewHolder {
        private SparseArray<View> viewHolder;
        private View view;
        public ViewHolder(View view) {
            this.view = view;
            viewHolder = new SparseArray<View>();
        }
        public <T extends View> T get(int id) {
            View childView = viewHolder.get(id);
            if (childView == null) {
                childView = view.findViewById(id);
                viewHolder.put(id, childView);
            }
            return (T) childView;
        }
        /**
         * 得到 view 下 id 为 id 的TextView 这里没有做类型的判断所以你要保证 id 为 id 的控件确实为 TextView类型
         * @param id
         * @return
         */
        public TextView getTextView(int id) {
            return get(id);
        }
        /**
         * 直接设置文字
         * @param id
         * @param text
         */
        public void setText(int id,String text){
            getTextView(id).setText(text);
        }
        public ImageView getImageView(int id) {
            return get(id);
        }
    }
}

现在结合上面两个类,我们可是实现了更简单的 adapter 写法
AutoAdapter.class

public abstract class AutoAdapter extends MBaseAdapter{
        /**
         * item 的布局文件
         */
        private int layoutID;
        /**
         * 这是一个生产 ViewHolder的工具类
         */
        private ViewHolderUtils vh;
        public AutoAdapter(Context context, List<?> list, int layoutID) {
            super(context, list);
            this.layoutID = layoutID;
            vh = new ViewHolderUtils();
        }
        @Override
        public View getView33(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = inflater.inflate(layoutID, parent, false);
            }
            getView33(position, convertView, vh.get(convertView));
            return convertView;
        }
        /**
         * 通过暴露这个方法,通过操作vh实现将数据的绑定在视图上
         * @param position
         * @param v
         * @param vh
         */
        public abstract void getView33(int position, View v, ViewHolderUtils.ViewHolder vh);
}

重点来了:
我们现在有一个适配器要写,怎么写呢,只要继承AutoAdapter,
我们只要实现了两个方法:getView33和它自身的构造方法,他就可以快速实现了适配器的编写,并且这个适配器是 Viewhodler 的形式.
例子:

public class DemoAdapter extends AutoAdapter {
    public DemoAdapter(Context context, List<?> list) {
        /**
         * 这里的 LayoutID 确定 ListView item 的布局资源文件.
         */
        super(context, list, R.layout.item);
    }
    /**
     * 将数据绑定在视图上
     */
    @Override
    public void getView33(int position, View v, ViewHolder vh) {
        Entity item=(Entity) list.get(position);
        vh.getTextView(R.id.name).setText(item.getName());
        vh.getTextView(R.id.age).setText(item.getAge());
        vh.setText(R.id.height,item.getHeight()); 
    }
}

在 Activity 中的使用:

 BaseAdapter adapter=new DemoAdapter(this, dateA);      
     listView.setAdapter(adapter);

为了方便大家,提供了 eclipse 版本的源码
源码放在 csdn中:http://download.csdn.net/detail/u010637692/8351645