在我们日常的开发中 避免不了使用listview控件,即使现在 google已经退出recyclerview 很久 ,但是listview一直在我们使用频率最高的列表展示控件,而且我们的使用套路已经模式化了 添加 listview控件-->创建adapter---在adapter里面创建viewholder—>在 adapter getview方法里面进行绑定 给每个控件 赋值。
首先我们按照一般的方式创建listview 设置
- public class GenAdapter extends BaseAdapter {
- private List<CityModel> mData;
- private Context mContext;
- public GenAdapter(List<CityModel> mData, Context mContext) {
- super();
- this.mData = mData;
- this.mContext = mContext;
- }
- @Override
- public int getCount() {
- return mData.size();
- }
- @Override
- public CityModel getItem(int pos) {
- return mData.get(pos);
- }
- @Override
- public long getItemId(int pos) {
- return pos;
- }
- @Override
- public View getView(int pos, View convertView, ViewGroup arg2) {
- CityModel model = mData.get(pos);
- View view = null;
- ViewHolder holder = null;
- if (convertView == null) {
- view = View.inflate(mContext, R.layout.item_city, null);
- holder = new ViewHolder();
- holder.tvCityName = (TextView) view.findViewById(R.id.tvCityName);
- holder.tvCityCode = (TextView) view.findViewById(R.id.tvCityCode);
- view.setTag(holder);
- } else {
- view = convertView;
- holder = (ViewHolder) view.getTag();
- }
- holder.tvCityName.setText(model.cityName);
- holder.tvCityCode.setText(model.cityCode);
- return view;
- }
- private static class ViewHolder {
- public TextView tvCityName, tvCityCode;
- }
- }
复制代码 如果我们写一个adapter 我们不会感觉 任何问题 但是如果 在app中经常出现呢??是不是还需要重复的写 这些呢? getCount() getItem(int pos) getItemId(int pos) 这三个方法很容易抽取出来 。
我们怎么处理ViewHolder 跟getView(int pos, View convertView, ViewGroup arg2) 呢?每次都需要写吗?
基于这些问题 有这一种方式,我们把ViewHolder独立出来 使用Map<int,View> 来保存 ConverView里面的控件
最终写的代码是这样的:
- public class ViewHolder {
- /**
- * listview 一个item的 所包含的view 都保存在里面
- */
- private SparseArray<View> mViews;
- private Context mContext;
- private int mPostion;
- private View mConvertView;
- private ViewHolder(Context context, ViewGroup parent, int layoutId,
- int postion) {
- this.mContext = context;
- this.mPostion = postion;
- this.mViews = new SparseArray<View>();
- mConvertView = LayoutInflater.from(mContext).inflate(layoutId, parent,
- false);
- mConvertView.setTag(this);
- }
- public static ViewHolder get(Context context, View convertView,
- ViewGroup parent, int layoutId, int postion) {
- if (convertView == null) {
- return new ViewHolder(context, parent, layoutId, postion);
- } else {
- ViewHolder holder = (ViewHolder) convertView.getTag();
- holder.mPostion = postion;
- return holder;
- }
- }
- public View getConvertView() {
- return mConvertView;
- }
- /**
- * 根据资源id获取 控件
- *
- * @param viewId
- * @return
- */
- public <T extends View> T getView(int viewId) {
- View v = mViews.get(viewId);
- if (v == null) {
- v = mConvertView.findViewById(viewId);
- mViews.put(viewId, v);
- }
- return (T) v;
- }
- }
复制代码
这样我们就完成了将ViewHolder 抽取出来了。这样还不是最 简洁 我们在处理一下 Adapter 首先 我们已经 知道 需要把getCount() getItem(int pos) getItemId(int pos) 抽取到父类中了 因此我们需要 使用泛型解决。 另外在 LIstView日常使用的时候我们经常需要 切换数据源(刷新) 或者增加(分页)因此我们把 这两个方法都抽取到父类 最终的实现 就是这样的:
- public abstract class CommonAdapter<T> extends BaseAdapter {
- protected List<T> mData;
- protected Context mContext;
- protected LayoutInflater mInflater;
- public CommonAdapter(Context mContext) {
- super();
- mData = new ArrayList<T>();
- this.mContext = mContext;
- this.mInflater = LayoutInflater.from(mContext);
- }
- @Override
- public int getCount() {
- return mData!=null?mData.size():0;
- }
- @Override
- public T getItem(int position) {
- return mData.get(position);
- }
- /**
- * 添加 数据集合
- * @param data
- */
- public void addData(List<T> data) {
- if (mData == null) {
- mData = new ArrayList<T>();
- }
- mData.addAll(data);
- notifyDataSetChanged();
- }
- /**
- * 添加一条数据
- * @param t
- */
- public void addItem(T t) {
- if (mData == null) {
- mData = new ArrayList<T>();
- }
- mData.add(t);
- notifyDataSetChanged();
- }
- /**
- * 添加指定位置的一条数据
- * @param pos
- * @param obj
- */
- public void addItem(int pos, T obj) {
- if (mData == null) {
- mData = new ArrayList<T>();
- }
- mData.add(pos, obj);
- notifyDataSetChanged();
- }
- /**
- * 移除一个item
- *
- * @param obj
- */
- public void removeItem(T obj) {
- mData.remove(obj);
- notifyDataSetChanged();
- }
- /**
- * 清空数据
- */
- public void clear() {
- if (mData != null) {
- mData.clear();
- }
- notifyDataSetChanged();
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder holder = ViewHolder.get(mContext, convertView, parent,
- getLayoutId(), position);
- convert(holder, getItem(position));
- return holder.getConvertView();
- }
- /**
- * 将数据赋值到 ui控件上
- *
- * @param holder
- * @param t
- */
- public abstract void convert(ViewHolder holder, T t);
- /**
- * item的布局id
- *
- * @return
- */
- public abstract int getLayoutId();
- }
复制代码
好了 我们先写一个例子 :
- public class FastAdapter extends CommonAdapter<CityModel> {
- public FastAdapter(Context mContext) {
- super(mContext);
- }
- @Override
- public void convert(ViewHolder holder, CityModel t) {
-
- holder.setText(R.id.tvCityName, t.cityName);
- holder.setText(R.id.tvCityCode, t.cityCode);
- }
- @Override
- public int getLayoutId() {
- return R.layout.item_city;
- }
- }
复制代码
FastAdapter跟GenAdapter 实现了相同的功能 或者说 比后者功能更强大,但是代码明显减少。如果 itenVIew中的控件再多一些的画 就会明显看出来了。
列子 附在附件 两个类的代码 好好研究是 确实能减轻自己不少 压力 提高代码的质量
注意 :不好意思 刚才 代码 编码是gbk的 各位注意了
|
|