您的位置:首页 > 移动开发 > Android开发

android之adapter的抽象与提炼

2016-03-22 13:54 435 查看
在网上关于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了,如果有什么不好的地方,望大神们指出!

另,这其中参考了慕课网里面的课程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: