一、概念和机制
适配器模式的使用,LisView的显示和数据源解耦。(这个先挖坑,在学了适配器模式之后会回来补充)
先看数据源、适配器和ListView之间的关系
ListView的缓存和显示机制:需要时候显示,划出屏幕时候被回收到缓存。
BaseAdapter要重写的几个方法:
然后就开始做一个ListView来看一下:
二、基本使用举例
1.ListView布局添加和子项Item的布局配置
首先需要像添加某一个View一样,在布局里面加一个ListView
然后给ListView每一个子项都需要一个布局,我们就做一个这样的布局:
2.创建子项Bean和数据提供
然后要给子项建一个Bean。我们这里建立一个ItemBean,包括了三部分内容图片,内容和标题:
然后在主活动里面搞一个List,造一些假的数据,这就是数据源:
3.Adapter的配置
需要一个List去接收数据源,然后前三个方法都比较水,不需解释。
最后一个getView是最关键的方法,它决定了每一项返回的内容。
第一步:需要一个LayoutInflater对象来把子项的XML文件加载成一个View对象。
这个LayoutInflater对象就是个布局装饰器对象,调用它的Inflate()方法,可以把一个XML转化成View。那么这个对象从何而来?他需要context来构建。我们在Adapter里面加以下代码,来构建这个对象:
第二步:重写getView方法
不要忘了return这个view
第三步:通过构造器构造Adapter绑定数据源和Adapter,然后通过ListView的setAdatper()绑定ListView和我们的Adapter
最后的效果
三、ListView的优化
上面是最基本一种构建Adapter的方式,不过我们看到getView中每次都在重新加载view,这实际上是十分不好的,效率低下我们在上面介绍机制的时候也是说ListView存在缓存机制,但是我们好像完全没有使用,是的,细心一点我们发现getView还有其他的参数都被我们无视了,实际上第二个参数convertView是缓存的关键。
我们下面就来利用一下缓存机制。
这里是避免了反复去inflate那个xml,这个Inflate方法十分之耗时,这样利用ListView提供的参数的确是节省了不少时间,但是我们还是想,有没有可能让每个布局里面的控件也不用每次都去重新findViewById呢?findViewById依然是很耗时的。当然我们是有方法的.
利用ViewHolder的终极优化:
第一步:创建一个ViewHolder类(一般是Adapter这块的内部类)
里面的三个字段就是我们要findViewById的那三个View。
第二步:新建ViewHolder引用。
如果没有缓存时候,实例化ViewHolder,把控件保存在ViewHolder对象中,即findViewById的结果全部给ViewHolder对象的字段,然后调用convertView的setTag方法,传入ViewHolder对象,建立起了convertView与ViewHolder之间的关系
如果有缓存了,调用convertView的getTag取得关联的对象,将返回结果赋给ViewHolder引用
这里也贴一下setTag和getTag的源码,看注释已经很清楚这是干什么的方法了:
第三步:直接给viewHolder中的成员去setText,setImageResource等等,并且返回convertView
这样呢我们就又避免了反复findViewById,完成了最终极的优化!