ListView优化adapter getview的两种方式ViewHolder vs HolderView

dimo 9年前

来自: http://www.jcodecraeer.com//a/anzhuokaifa/androidkaifa/2014/1021/1814.html


一、ViewHolder方式

如果你还没听说过ViewHolder,那么你该去好好看看官方文档了,而不是埋头写代码。

一个ListView的item布局中需要赋值的子元素太多为了避免重复的调用FindViewById方法,我们一般考虑使用ViewHolder方式来实现BaseAdapter。

如下:

//在外面先定义,ViewHolder静态类  static class ViewHolder  {      public ImageView img;      public TextView title;      public TextView info;  }  //然后重写getView  @Override  public View getView(int position, View convertView, ViewGroup parent) {      ViewHolder holder;      if(convertView == null)      {          holder = new ViewHolder();          convertView = mInflater.inflate(R.layout.list_item, null);          holder.img = (ImageView)item.findViewById(R.id.img)          holder.title = (TextView)item.findViewById(R.id.title);          holder.info = (TextView)item.findViewById(R.id.info);          convertView.setTag(holder);      }else      {          holder = (ViewHolder)convertView.getTag();      }          holder.img.setImageResource(R.drawable.ic_launcher);          holder.title.setText("Hello");          holder.info.setText("World");      }                                                                                                                                                                                                                                                                                                                                                       return convertView;  }

ViewHolderconvertView第一次inflate的时候绑定了相关的子元素,并被convertView保存下来(setTag方法),当相同的convertView再次需要显示的时候直接调用convertView的getTag取出ViewHolder,并对ViewHolder中的元素赋值。使用ViewHolder模式避免了没有必要的调用findViewById():因为太多的findViewById也会影响性能,这点不容易考虑到。

 

二、HolderView方式

在HolderView方式中,目的同样是为了避免反复的调用findViewById,但是我们将这个findViewByIdde 任务交给了一个HolderView对象

@Override  public View getView(int i, View convertView, ViewGroup viewGroup) {      HolderView holderView;      // Important to not just null check, but rather to a instanceof      // since we might get any subclass of view here.      if (convertView instanceof HolderView) {          holderView = (HolderView) convertView;      } else {          holderView = new HolderView(mContext);      }      holderView.bind("标题", R.drawable.ic_launcher, "sajsa");      return holderView;  }  public class HolderView extends GridLayout {      private ImageView img;      private TextView title;      private TextView info;      public HolderView(Context context, AttributeSet attrs) {          super(context, attrs);          View v = LayoutInflater.from(context).inflate(R.layout.list_item, this);          title = (TextView) v.findViewById(R.id.title);          img = (ImageView)item.findViewById(R.id.img)          info = (TextView)item.findViewById(R.id.info);      }      public void bind(String stringtitle,int imgrsc, String stringinfo) {          title.setText(stringtitle);          img.setImageResource(imgrsc);          info.setText(stringinfo);      }  }

HolderView自己维护一个子元素的集合,同时对外提供绑定数据的公共方法bind。HolderView方式的思想是:对于ListView来讲,每一个Item本身是同一个类只是数据不同。但是需要注意的是使用HolderView方式在Adapter中getView返回的是HolderView对象。

总结:ViewHolder方式使用简单,HolderView方式更符合面向对象规范。