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...