android中像是ListView和girdview 这种组件在项目中使用频率非常高, adapter 也是每次必写的玩意 合理的封装 优化 可以使得我们的写更少的代码 做更多的事情.
以下文章阐述了如何从80行代码 优化到 25行
ViewHolder 优化
传统的ViewHolder 一般都在自定义的adapter去编写,并且每一个adapter都会对应一个自定义的内部类viewholder.
MyAdapter 中 viewHolder 部分代码:
private class ViewHolder{TextView userName; TextView userAge; TextView userAddress; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView == null){ convertView = mInflater.inflate(this.layout,parent,false); holder = new ViewHolder(); holder.userName = (TextView) convertView.findViewById(R.id.user_name); holder.userAge = (TextView) convertView.findViewById(R.id.user_age); holder.userAddress = (TextView) convertView.findViewById(R.id.user_address); convertView.setTag(holder); } else{ holder = (ViewHolder) convertView.getTag(); } return convertView; }
优化方案 : 将各零散 viewHolder 抽象成一个通用类 适配所有自定义的adapter 并且viewHolder的相关业务 从adapter中 放到 通用viewHolder中.
抽象之后 使用通用viewHolder 1行代码
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
return viewHolder.getConvertView();
}
获得控件我们就可以用通用类中封装好的方法getView(int id)
TextView textView = viewHolder.getView(R.id.user_name);
以下 ViewHolder 公共类 :
/**
抽象公共的viewholder
-
Created by sherlock on 15/12/17.
*/
public class ViewHolder {private SparseArray
mViews;
private int mPosition;
private View mConvertView;public ViewHolder(Context context, ViewGroup parent, int layoutId, int position) {
this.mPosition = position;
this.mViews = new SparseArray<>();
this.mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);mConvertView.setTag(this);
}
/**
- 获取viewholder
- @param context
- @param converView
- @param parent
- @param position
- @param layoutId
- @return
*/
public static ViewHolder get(Context context, View converView, ViewGroup parent, int position, int layoutId) {
if (converView == null) {
return new ViewHolder(context, parent, layoutId, position);
} else {
ViewHolder holder = (ViewHolder) converView.getTag();
//viewholderr会被复用 及时更新下position
holder.mPosition = position;
return holder;
}
}
/**
* 取得viewholder存储的的控件
* @param viewId
* @param
* @return
*/
public T getView(int viewId) {
View view = mViews.get(viewId);
if(view == null){
view = mConvertView.findViewById(viewId);
mViews.put(viewId,view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
}
Adapter优化
我们建立一个CommonAdapter 继承自BaseAdapter
public abstract class CommonAdapter
extends BaseAdapter { protected LayoutInflater mInflater; protected int layout; protected Context context; protected List
dataList; public CommonAdapter(Context context, int layout, List dataList) { this.context = context; this.layout = layout; this.dataList = dataList; this.mInflater.from(context); } @Override public int getCount() { return dataList.size(); } @Override public T getItem(int position) { return dataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public abstract View getView(int position, View convertView, ViewGroup parent); }
使用commonAdapter,代码是不是精简很多 我们还可以继续优化:
public class MyAdapter extends CommonAdapter{ public MyAdapter(Context context, int layout,List
dataList) { super(context,layout,dataList); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout); //使用 TextView textView = viewHolder.getView(R.id.user_name); return viewHolder.getConvertView(); } }
我可以做到让使用者更加专注他们的业务, 可以将
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
return viewHolder.getConvertView();
两部分代码 继续封装 复用
在CommonAdapter中加入 一个抽象方法
public abstract void convert(ViewHolder holder,T t);
在commonAdapter中实现getView
@Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder viewHolder = ViewHolder.get(context, convertView, parent, position, layout);
convert(viewHolder,getItem(position));
return viewHolder.getConvertView();
}
我们的MyAdapter来实现convert 这个部分就是暴露给 使用者的部分 在这里可以拿到一个holde如和 对应业务bean的俩个对象 让你专注填业务
超级清爽
public class MyAdapter extends CommonAdapter{ public MyAdapter(Context context, int layout,List
dataList) { super(context,layout,dataList); } @Override public void convert(ViewHolder holder, User user) { //使用 TextView textView = holder.getView(R.id.user_name); textView.setText(user.getUserName()); } }
极限优化 1行代码
我们可以通过链式调用来实现这个效果,我们在ViewHolder中 写2个辅助方法
public ViewHolder setText(int viewId,String text){
TextView textView = getView(viewId);
textView.setText(text);
return this;
}public ViewHolder setImageResource(int viewId,int resId){
ImageView imageView = getView(viewId);
imageView.setImageResource(resId);
return this;
}
可以根据你的控件情况 来封装不同的方法.
使用起来很easy了 呵呵 真的一行足矣
public class MyAdapter extends CommonAdapter
{ public MyAdapter(Context context, int layout, List
dataList) { super(context, layout, dataList); } @Override public void convert(ViewHolder holder, User user) { holder .setText(R.id.user_name, user.getUserName()) .setText(R.id.user_age, user.getUserAge()) .setText(R.id.user_address, user.getUserAddress()); } }