本篇文章可能有点长,请网友多点耐心的阅读。或者也可以一段一段的阅读,每段的内容都是ListView优化的一个点。
___在使用ListView时,我们每次都要先获取item的每个view,所以每次都会先getViewById。但是只要一获取组,那么肯定会有一个耗时的操作,所以我们将它写在ViewHolder中。不过ViewHolder只是将需要缓存的View封装起来,而convertView的setTag才是将这些封装好的View缓存起来供下次使用。
___而ViewHolder自身也是一个静态内部类,静态内部类不持有外部类的引用,可以避免内存泄漏。在Android中,很多的内存泄漏都是由于在Activity中使用了非静态内部类导致的。因为如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄漏。我个人更倾向于使用静态类和弱引用的方法解决这种问题。
___ListView中加载图片的时候,可以用异步加载。在加载的时候它会新启一个线程,并不会影响主线程工作。
___还有就是对图片进行3级缓存。缓存的话它是首先存储在强引用LruCache中,存不下之后存在软引用SoftRerences中,同时也会存在本地的SD卡中。因为强引用与软引用是在运行时的内存中,虽然容量小,但是读取快,并且程序一旦突出,原先存储的数据便会清空。而本地的SD卡虽然可以存储大量数据,但是它读取慢,并且程序退出后,原先存储的数据并不会清空,需要我们手动清空。
___解析图片的时候我们可以用Bitmap,它会将图片完整的解析出来,并且按照图片的分辨率转换出来,不过会占很大的内存,很容易出问题。尤其是图片过大的话,可能会使内存的不够用,而导致内存溢出。我们可以在ListView中去加载图片的缩略图,而当用户点击图片之后,在重新启动一个fragment/activity/对话框等等,去显示整个图片。
___直接使用ImageView去显示Bitmap也会占用较多的资源,特别是图片较大的时候,可能会导致程序崩溃。我们可以使用BitmapFactory.Options设置inSampleSize,这样做可以减少对系统资源的要求。属性值inSampleSize表示缩略图大小为原始图片的几分之一。比如这个值为2,那么缩略图的宽与高都是原始图片的1/2,图片的大小就为原始图片的1/4。
___还有图片的像素问题,Android的图片像素有四种属性:
1、ALPHA_8:每个像素占用1Byte内存
2、ARGB_4444:每个像素占用2Byte内存
3、ARGB_8888:每个像素占用4Byte内存(默认)
4、RGB_565:每个像素占用2Byte内存
Android默认的颜色模式为ARGB_8888,这个颜色最为细腻,显示的质量最高。但同时它也最耗用内存。所以我们对图片效果要求不是特别高的话,可以使用RGB_565(没有透明度属性)。
___当我们使用完Bitmap之后,一定要记得调用Bitmap.recycle()方法来释放Bitmap所占用的内存空间,不然会很容易造成内存泄漏。
___因为convertView的重用,我们在快速滑动ListView时,会导致ImageView会有多个不同的网址同时进行异步加载,这样比较容易导致图片的多次错乱。我们可以给ImageView设置一个Tag,这个Tag就相当于一个url,在异步任务设置图片时,需要检测一下将要加载url与ImageView的Tag是否一致,一致便设置图片。还有便是当ListView快速滑动时,图片与文本可以设置为默认的图片与文本,不进行加载;当停止滑动后,在开启网络加载图片与信息,刷新自身的正确数据。