OuNuo0 2015-02-12
android中listView如何复用多种布局
我们都知道,当listView的item比较多的时候,会利用convertView对每个item进行缓存
但是这还不够,当我们的每个item布局中的控件比较多的时候,我们还会用ViewHolder对每个item布局中的view进行缓存,达到减少调用findViewById的次数目的,这样会让你的listView的滑动的时候会比较顺畅。
viewHolder复用一个布局的话,我相信谁都会,但是现实开发中往往我们会复用多个布局,这个时候我们该如何实现呢?
adapter填充数据的时候,我们一般要实现以下方法:
1 public int getCount(){ }
2 public Object getItem(int position) {}
3 public long getItemId(int position) {}
4 public View getView(int position, View view, ViewGroup viewGroup){}
但是要实现复用多种布局的话我们还要实现下面2个方法
1 public int getItemViewType(int position) {}
返回我们要复用的布局类型,假如我们要复用一个tab结构和item结构,我们可以这么来写
类别的数值在(0,类别总数-1)之间
public static final int TYPE_UNKNOW = 0; public static final int TYPE_TAB = 1; public static final int TYPE_LIST_ITEM = 2; public static final int TYPE_MAX_COUNT = 3; @Override public int getItemViewType(int position) { //复用tab结构 if (position == 1) { return TYPE_TAB; } //复用一般的item结构 int size = CollectionUtils.size(feedDataList); if (position >= 1 && size > 0 && position < (size + 2)) { return TYPE_LIST_ITEM; } return TYPE_UNKNOW; }
类别总数是3,类别对应的int值应该在0 - 2 之间,它们分别是
public static final int TYPE_UNKNOW = 0; public static final int TYPE_TAB = 1; public static final int TYPE_LIST_ITEM = 2;
2 public int getViewTypeCount() { } 返回复用布局的总数,这里是3
@Override public int getViewTypeCount() { return TYPE_MAX_COUNT; }
在adapter中的getView方法中,我们就可以这样来写:
@Override public View getView(int position, View convertView, ViewGroup viewGroup) { ItemViewHolder itemViewHolder; TabViewHolder tabViewHolder; int viewType= getItemViewType(position); switch (viewType) { case TYPE_TAB: if(convertView == null ) { tabViewHolder = new TabViewHolder(mContext); //给contenView赋值,并给viewHolder设置tag tabViewHolder.findView(position,convertView,viewGroup); }else{ //直接复用 tabViewHolder = (TabViewHolder)convertView.getTag(); } //这里是处理业务逻辑的方法 tabViewHolder.setView(position); return tabViewHolder.layout;//返回convertView case TYPE_LIST_ITEM: if (convertView == null) { itemViewHolder = new ItemViewHolder(mContext); //给contenView赋值,并给viewHolder设置tag itemViewHolder.findView(position, convertView, viewGroup); } else { //convertView不为空,直接复用 itemViewHolder = (ItemViewHolder) convertView.getTag(); } //处理业务逻辑 itemViewHolder.setView((FeedComment)getItem(position)); return itemViewHolder.layout;//返回convertView case TYPE_UNKNOW: return null; } return null; }
说明:处理复用多个布局的时候,如果不调用上面getViewTypeCount()和getItemType(),很容易就出现viewHolder类型转换错误。因为在屏幕滚动的时候,view.getTag()返回的viewHolder有2种,我们拿到的viewHolder可能就不是理想中的viewHolder,这个时候类型转换错误就出现了。