列表显示需要三个元素,
(1)listview 视图,用来显示列表的View ;
(2)适配器,用来把数据映射到listView上面的
(3)数据,具体将被映射的数据,包括字符串,图片或者基本自定义的组件也行。
适配器分为三种,
ArrayAdapter,SimpleAdapter和SimpleCursorAdapter
这三者的区别不过是数据源不同而已。
ArrayAdapter就是数组适配器,具体的就是字符串数组;
SimpleAdapter就是简单适配器,但是不太简单,它的数据源就是List<Map<String,?>>,可以在Map里面放上各种各样的组件。
SimpleCursorAdapter 简单游标适配器,以数据库查询而来的游标作为数据源。
说完分类后再说ListView 的工作原理
Android系统在绘制ListView之前,先调用 getCount()方法,来获得将要绘制的列表有多长。然后调用getView方法,来获得一个View或者复杂一点的就是ViewGroup 。有几个listView子项,在屏幕最多能显示的前提下,显示最多个,比如说屏幕能显示5个,而getCount()返回10个,那么这首先显示的5个Item就是返回了5个View,进行显示的。但是当下滑的时候,是不是又新建返回一个View呢?假如有上千万个呢?显然这样新建的话,最终内存会被耗尽。Android 已经做了优化,有个构件,叫做Recycler,它负责存放失去显示的子项View对象,比如说1~5号view在显示,现在往上滑动,1号view就进入Recycler,由于马上第六条的显示就需要用到一个view,那么这时候回收了的1号view就会授予给6号,进行显示,而不必新建一个view对象了,从而节省和优化内存。
下面说优化方案:
(1)使用自定义的视图缓存类
就是自定义一个视图缓存类,在这个类中保存我们在item中使用到的视图的引用,通过convertView的setTag方法和getTag方法来存储这个视图缓存类引用和重新获取这个视图缓存类引用,其目的也是为了减少重复创建视图时的开销。tag就是标签的意思,但是,它不像ID一样用来表示view的,从本质上讲它是与某一个view绑定的额外的信息,setTag(Object obj)中输入就是对象,可以是任意的对象信息。
(2)如果listview子项中包括图片,不要直接加载到内存里,因为你不知道图片有多大,而虚拟机中分配给堆的内存最大只有16M那么少。很容易就出现OOM。为了避免这种情况,可以对图片进行两步操作,一是利用BitmapFactory.Options()这个方法可以不加载图片到内存而获得图片大小,然后就对图片进行边界压缩;第二步是使用软引用来代替强引用来存储图片的引用。如可定义这么一个图片缓存。
private Map<String, SoftReference<Bitmap>> imageCache = Collections
.synchronizedMap(new LinkedHashMap<String, SoftReference<Bitmap>>(
10, 0.75f, false));
(3)避免在ListView中使用线程,因为线程的生命周期不可控制,你不知道它什么时候执行完毕,容易造成内存泄漏。
文章评论(0条评论)
登录后参与讨论