android中像是ListView和girdview 这种组件在项目中使用频率很是高, adapter 也是每次必写的玩意 合理的封装 优化 可使得咱们的写更少的代码 作更多的事情.android
如下文章阐述了如何从80行代码 优化到 25行ide
传统的ViewHolder 通常都在自定义的adapter去编写,而且每个adapter都会对应一个自定义的内部类viewholder.优化
MyAdapter 中 viewHolder 部分代码:this
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中.spa
抽象以后 使用通用viewHolder 1行代码code
@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<View> 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 <T> * @return */ public <T extends View> 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; } }
咱们创建一个CommonAdapter 继承自BaseAdapterrem
public abstract class CommonAdapter<T> extends BaseAdapter { protected LayoutInflater mInflater; protected int layout; protected Context context; protected List<T> dataList; public CommonAdapter(Context context, int layout, List<T> 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,代码是否是精简不少 咱们还能够继续优化:get
public class MyAdapter extends CommonAdapter<User> { public MyAdapter(Context context, int layout,List<User> 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<User> { public MyAdapter(Context context, int layout,List<User> 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()); } }
咱们能够经过链式调用来实现这个效果,咱们在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<User> { public MyAdapter(Context context, int layout, List<User> 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()); } }
文章同步发布在 http://www.jianshu.com/p/1d80...