getview

最近在做android相关的开发,ListView中有一个图片错位的问题,今天查了很多人写的一些东西,所以记录下来,算是一种加深理解吧。
 
 
 
ListView是一个非常常用的控件,功能可以扩展的很丰富,而且与GridView有很多相似的地方。都可以存放大量数据。而且当我们需要比较复杂的布局时,一般用SimpleAdapter,或者继承BaseAdapter自己重写。
 
 如果是继承ArrayAdapter,SimpleAdapter的时候,由于父类本身维护了一个List,所以当有数据更新的时候,尽量用adapter的add,这样可以保证getCount()返回的值是正确。
 
这里面涉及到的一个比较重要的重写函数就是getView
 
 
 
在getView中有三种方式实现view的返回。
 
 
 
第一种方式:
 
最简单也是最容易理解的是每一个view都通过inflate生成一个新的view进行返回
 
public View getView(int position, View convertView, ViewGroup parent) {
    
     LayoutInflater inflater = LayoutInflater.from(context);
     
     View item = inflater.inflate(R.layout.list_item_icon_text, null);
 
     ((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
     ((ImageView) item.findViewById(R.id.icon)).setImageBitmap(
  
     return item;
}
这种方式,在数据量小的时候,劣势不明显,但是当一个listview里面有大量条目时,这种方式就显得非常浪费。因为每一次item的出现,消失或者更新时,都需要重新inflate。给内存造成了很大的消耗。
 
那么还有什么方式可以节省开销呢?
 
 
 
第二种方式:
 
我们看看getView函数里面conertview的是干啥的。查看官方文档后发现:
 
convertView - The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view. Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see Adapter.getViewTypeCount() and Adapter.getItemViewType(int)).
 
 
注:
 
getViewTypeCount()是用来当listview中有不同的种类的item,比如分割线之类的时候,用getItemViewType返回某个item的类型,然后坐不同的
 
 
原来converView是用来重用view的。经过查找别的资料。找到了一张比较经典的图如下:
 
 
 
 
 
这张图清楚的描述了listview是如何重用view的。listview通过getview分别请求所有可见项目。此时converview是空的。
 
当item1滑动出屏幕后,item8从下面滑动出来,此时又要调用getview,但是此时的converview已经不再为空了,而是上次一划出屏幕的item1,此时我们只需要重新修改下item1的数据,而不必重新创建一个新的view。
 
这样就节省了内存。
 
 
 
那么由此我们得到了第二种方式
 
 
public View getView(int position, View convertView, ViewGroup parent) {
 if (convertView == null) {
   convertView = mInflater.inflate(R.layout.item, parent, false);
 }
   ((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
   ((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(
   (position & 1) == 1 ? mIcon1 : mIcon2);
   return convertView;
 }
 
 
 
这种方式里面,我们通过converview找到对应需要修改的text和ico,然后修改数据,进行返回。
 
 
 
有人会说,上面不已经解决了重用的问题了么,还有第三种方式?
 
 
 
那么我们下面看看google推荐的第三种方式是怎么实现的。
 
 
 
static class ViewHolder {
TextView text;
ImageView icon;
}
 
 
这里定义了一个内部静态类,
 
 
public View getView(int position, View convertView, ViewGroup parent) {
 ViewHolder holder;
 
 if (convertView == null) {
 convertView = mInflater.inflate(R.layout.list_item_icon_text,
 parent, false);
 holder = new ViewHolder();
 holder.text = (TextView) convertView.findViewById(R.id.text);
 holder.icon = (ImageView) convertView.findViewById(R.id.icon);
 convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}
 
 
 
 
 
然后用convertView.setTag(holder)的方式将之前通过findViewById找到的textview与ImageView放入converivew对象中。
 
这样当再次重用converview的时候,就不必再次利用findViewById来查找了,省掉了开销。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值