android之adapter的抽象与提炼

在网上关于adpter的文章太多了,大多都是对adapter中的getView()方法如何优化之类的,然后逐渐形成一种公认的adatper模板,大致如下:

public class ESAdapter extends BaseAdapter {
@Override
	public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
              //TODO ...
        }
        //TODO ...
   }
     class ViewHolder{
         //TODO ...
      }
}
主要是在getView()里面对缓存的converView判断了再做处理,然后再添加一个内部类来管理item模板里同的view。当然,这样做没什么问题,今天要说的并不是这个,而是对这个adapter做进一步的提炼。试想,能不能把这个ViewHolder抽象出来,否则每建一个adapter都必须加上一个内部类;其次,getView()方法里面的结构也是一模一样,是否也可以把getView()进一步提炼,当然,这两者是有关联的,既然想到这些可以让代码更简洁的问题,那今天就对这种模板化的adapter做一下升级了,哈哈~


其实主要做法就是把以前的内部类ViewHolder提炼成一个公共的ViewHolder,这样就可以复用了,代码如下:

/**
 * used in adapter
 * 
 * @author levi.li
 *
 */
public class ViewHolder {
	private SparseArray<View> mViews;
	private int mPosition;
	private View mConvertView;

	private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
		this.mPosition = position;
		this.mViews = new SparseArray<View>();
		this.mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
		this.mConvertView.setTag(this);
	}

	public static ViewHolder get(Context context, View convertView, ViewGroup parent, int layoutId, int position) {
		if (convertView == null) {
			return new ViewHolder(context, parent, layoutId, position);
		}
		ViewHolder holder = (ViewHolder) convertView.getTag();
		holder.mPosition = position;
		return holder;
	}

	public int getPosition() {
		return mPosition;
	}

	/**
	 * get view by viewId
	 * 
	 * @param viewId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	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;
	}

	/**
	 * set value to TextView
	 * 
	 * @param id
	 * @param text
	 * @return
	 */
	public ViewHolder setTextView(int id, String text) {
		((TextView) getView(id)).setText(text);
		return this;
	}

	/**
	 * set value to CheckBox
	 * 
	 * @param id
	 * @param b
	 * @return
	 */
	public ViewHolder setCheckBox(int id, boolean b) {
		((CheckBox) getView(id)).setChecked(b);
		return this;
	}

	public View getConvertView() {
		return this.mConvertView;
	}
}
对于get(),这里主要是把原先getView()里面对convertView的判断抽出来,对ViewHolder内部类的抽象,主要体现在getView和set方法上,并将这些view存在SparseArray中;

ViewHolder抽出来之后,来看下adapter怎么实现

/**
 * base adapter, used as ListView's adapter
 * 
 * @author levi.li
 *
 */
public abstract class ESBaseAdapter<T> extends BaseAdapter {

	protected Context mContext;
	protected List<T> mData;
	protected int mLayoutId;

	public ESBaseAdapter(Context context, List<T> listData, int layoutId) {
		this.mContext = context;
		this.mData = listData;
		this.mLayoutId = layoutId;
	}

	@Override
	public int getCount() {
		return mData.size();
	}

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

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder = ViewHolder.get(this.mContext, convertView, parent, this.mLayoutId, position);
		setViews(holder, getItem(position));
		return holder.getConvertView();
	}

	/**
	 * set value to View . this method must override in child adapter class
	 * 
	 * @param holder
	 * @param t
	 */
	public abstract void setViews(ViewHolder holder, T t);

这里将之前子view的实现用setView这个抽像方法来实现了,这样就可以动态的添加需要的view。


好了,所有的东西都提出来了,现在来看看怎么去继承这个新的adapter

public class TestAdapter extends ESBaseAdapter<TestModel<String>> {

	public TestAdapter(Context context, List<TestModel<String>> listData) {
		super(context, listData, R.layout.test_pulltorefresh_list_item);
	}

	@Override
	public void setViews(ViewHolder holder, final TestModel<String> model) {
		holder.setTextView(R.id.test_pulltorefresh_item_text, model.testDescription);

		final CheckBox cb = holder.getView(R.id.test_pulltorefresh_item_check);
		cb.setChecked(model.testFlag);
		cb.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				model.testFlag = cb.isChecked();
			}
		});
	}

}
很简单了,里面只需要重写setView就好了。


ok,这个adapter到此为止,以后就可以像这样简单的去写每个adapter了,如果有什么不好的地方,望大神们指出!

另,这其中参考了慕课网里面的课程


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值