A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始


在我们日常的开发中 避免不了使用listview控件,即使现在 google已经退出recyclerview 很久 ,但是listview一直在我们使用频率最高的列表展示控件,而且我们的使用套路已经模式化了 添加 listview控件-->创建adapter---在adapter里面创建viewholder—>在 adapter getview方法里面进行绑定 给每个控件 赋值。

  首先我们按照一般的方式创建listview  设置
  1. public class GenAdapter extends BaseAdapter {

  2.         private List<CityModel> mData;
  3.         private Context mContext;

  4.         public GenAdapter(List<CityModel> mData, Context mContext) {
  5.                 super();
  6.                 this.mData = mData;
  7.                 this.mContext = mContext;
  8.         }

  9.         @Override
  10.         public int getCount() {
  11.                 return mData.size();
  12.         }

  13.         @Override
  14.         public CityModel getItem(int pos) {
  15.                 return mData.get(pos);
  16.         }

  17.         @Override
  18.         public long getItemId(int pos) {
  19.                 return pos;
  20.         }

  21.         @Override
  22.         public View getView(int pos, View convertView, ViewGroup arg2) {
  23.                 CityModel model = mData.get(pos);
  24.                 View view = null;
  25.                 ViewHolder holder = null;
  26.                 if (convertView == null) {
  27.                         view = View.inflate(mContext, R.layout.item_city, null);
  28.                         holder = new ViewHolder();
  29.                         holder.tvCityName = (TextView) view.findViewById(R.id.tvCityName);
  30.                         holder.tvCityCode = (TextView) view.findViewById(R.id.tvCityCode);
  31.                         view.setTag(holder);
  32.                 } else {
  33.                         view = convertView;
  34.                         holder = (ViewHolder) view.getTag();
  35.                 }

  36.                 holder.tvCityName.setText(model.cityName);
  37.                 holder.tvCityCode.setText(model.cityCode);

  38.                 return view;
  39.         }

  40.         private static class ViewHolder {
  41.                 public TextView tvCityName, tvCityCode;
  42.         }

  43. }
复制代码
如果我们写一个adapter 我们不会感觉 任何问题 但是如果 在app中经常出现呢??是不是还需要重复的写 这些呢? getCount() getItem(int pos)  getItemId(int pos)  这三个方法很容易抽取出来 。
我们怎么处理ViewHolder 跟getView(int pos, View convertView, ViewGroup arg2) 呢?每次都需要写吗?
基于这些问题 有这一种方式,我们把ViewHolder独立出来 使用Map<int,View> 来保存 ConverView里面的控件  
最终写的代码是这样的:
  1. public class ViewHolder {

  2.         /**
  3.          * listview 一个item的 所包含的view 都保存在里面
  4.          */
  5.         private SparseArray<View> mViews;
  6.         private Context mContext;
  7.         private int mPostion;
  8.         private View mConvertView;

  9.         private ViewHolder(Context context, ViewGroup parent, int layoutId,
  10.                         int postion) {
  11.                 this.mContext = context;
  12.                 this.mPostion = postion;
  13.                 this.mViews = new SparseArray<View>();
  14.                 mConvertView = LayoutInflater.from(mContext).inflate(layoutId, parent,
  15.                                 false);
  16.                 mConvertView.setTag(this);
  17.         }

  18.         public static ViewHolder get(Context context, View convertView,
  19.                         ViewGroup parent, int layoutId, int postion) {
  20.                 if (convertView == null) {
  21.                         return new ViewHolder(context, parent, layoutId, postion);
  22.                 } else {
  23.                         ViewHolder holder = (ViewHolder) convertView.getTag();
  24.                         holder.mPostion = postion;
  25.                         return holder;
  26.                 }
  27.         }

  28.         public View getConvertView() {
  29.                 return mConvertView;
  30.         }

  31.         /**
  32.          * 根据资源id获取 控件
  33.          *
  34.          * @param viewId
  35.          * @return
  36.          */
  37.         public <T extends View> T getView(int viewId) {

  38.                 View v = mViews.get(viewId);
  39.                 if (v == null) {
  40.                         v = mConvertView.findViewById(viewId);
  41.                         mViews.put(viewId, v);
  42.                 }
  43.                 return (T) v;
  44.         }
  45. }
复制代码

这样我们就完成了将ViewHolder 抽取出来了。这样还不是最 简洁 我们在处理一下 Adapter 首先 我们已经 知道 需要把getCount() getItem(int pos)  getItemId(int pos)  抽取到父类中了 因此我们需要 使用泛型解决。 另外在 LIstView日常使用的时候我们经常需要 切换数据源(刷新) 或者增加(分页)因此我们把 这两个方法都抽取到父类 最终的实现 就是这样的:
  1. public abstract class CommonAdapter<T> extends BaseAdapter {

  2.         protected List<T> mData;
  3.         protected Context mContext;
  4.         protected LayoutInflater mInflater;

  5.         public CommonAdapter(Context mContext) {
  6.                 super();
  7.                 mData = new ArrayList<T>();
  8.                 this.mContext = mContext;
  9.                 this.mInflater = LayoutInflater.from(mContext);
  10.         }

  11.         @Override
  12.         public int getCount() {
  13.                 return mData!=null?mData.size():0;
  14.         }

  15.         @Override
  16.         public T getItem(int position) {
  17.                 return mData.get(position);
  18.         }

  19.         /**
  20.          * 添加 数据集合
  21.          * @param data
  22.          */
  23.         public void addData(List<T> data) {
  24.                 if (mData == null) {
  25.                         mData = new ArrayList<T>();
  26.                 }
  27.                 mData.addAll(data);
  28.                 notifyDataSetChanged();
  29.         }

  30.         /**
  31.          * 添加一条数据
  32.          * @param t
  33.          */
  34.         public void addItem(T t) {
  35.                 if (mData == null) {
  36.                         mData = new ArrayList<T>();
  37.                 }
  38.                 mData.add(t);
  39.                 notifyDataSetChanged();
  40.         }

  41.         /**
  42.          * 添加指定位置的一条数据
  43.          * @param pos
  44.          * @param obj
  45.          */
  46.         public void addItem(int pos, T obj) {
  47.                 if (mData == null) {
  48.                         mData = new ArrayList<T>();
  49.                 }
  50.                 mData.add(pos, obj);
  51.                 notifyDataSetChanged();
  52.         }

  53.         /**
  54.          * 移除一个item
  55.          *
  56.          * @param obj
  57.          */
  58.         public void removeItem(T obj) {
  59.                 mData.remove(obj);
  60.                 notifyDataSetChanged();
  61.         }

  62.         /**
  63.          * 清空数据
  64.          */
  65.         public void clear() {
  66.                 if (mData != null) {
  67.                         mData.clear();
  68.                 }
  69.                 notifyDataSetChanged();
  70.         }

  71.         @Override
  72.         public long getItemId(int position) {
  73.                 return position;
  74.         }

  75.         @Override
  76.         public View getView(int position, View convertView, ViewGroup parent) {
  77.                 ViewHolder holder = ViewHolder.get(mContext, convertView, parent,
  78.                                 getLayoutId(), position);
  79.                 convert(holder, getItem(position));
  80.                 return holder.getConvertView();
  81.         }

  82.         /**
  83.          * 将数据赋值到 ui控件上
  84.          *
  85.          * @param holder
  86.          * @param t
  87.          */
  88.         public abstract void convert(ViewHolder holder, T t);

  89.         /**
  90.          * item的布局id
  91.          *
  92.          * @return
  93.          */
  94.         public abstract int getLayoutId();

  95. }
复制代码

好了 我们先写一个例子 :
  1. public class FastAdapter extends CommonAdapter<CityModel> {

  2.         public FastAdapter(Context mContext) {
  3.                 super(mContext);
  4.         }

  5.         @Override
  6.         public void convert(ViewHolder holder, CityModel t) {
  7.                
  8.                 holder.setText(R.id.tvCityName, t.cityName);
  9.                 holder.setText(R.id.tvCityCode, t.cityCode);
  10.         }

  11.         @Override
  12.         public int getLayoutId() {
  13.                 return R.layout.item_city;
  14.         }

  15. }
复制代码

FastAdapter跟GenAdapter 实现了相同的功能  或者说 比后者功能更强大,但是代码明显减少。如果 itenVIew中的控件再多一些的画 就会明显看出来了。
列子 附在附件 两个类的代码 好好研究是 确实能减轻自己不少 压力 提高代码的质量

注意 :不好意思 刚才 代码 编码是gbk的 各位注意了

DemoList.zip

1.07 MB, 下载次数: 98

评分

参与人数 1技术分 +1 收起 理由
耀阳圣尊 + 1

查看全部评分

8 个回复

倒序浏览
还没学,但不过感觉好高级
回复 使用道具 举报
不明觉厉呢。
回复 使用道具 举报
略高端,大神自己写的吗
回复 使用道具 举报
虽然现在看不懂,但以后应该能用上,先收藏了
回复 使用道具 举报
已阅~~~~
回复 使用道具 举报
不要沉。。。啊
回复 使用道具 举报
非常好的容器,做下拉菜单的神器
回复 使用道具 举报
我去  这么多
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马