Android 性能优化——之图片的优化
在Android性能优化中,我们会发现占内存最大的和对性能影响最大的往往是图片资源,其次是控件资源。相对来说,其他的资源的影响会小一点。这里我就先对图片资源的优化进行一下讲解,如果有什么说的不对的,希望大神指正一下。
1、首先我们可以对图片进行二次采样,从本质上减少图片的内存占用。就是将大图片缩小之后放入到内存中,以实现减小内存的目的。代码如下:
1 //创建缩略图 2 private Bitmap onCreateThumbnail(String filePath2, int i) { 3 4 //得到选项 5 BitmapFactory.Options options=new BitmapFactory.Options(); 6 //设置为不读内容,值读取边界值 7 options.inJustDecodeBounds=true; 8 //通过编辑,得到边界值,并存入到option中 9 BitmapFactory.decodeFile(filePath2,options); 10 //得到缩放比例 11 int ratiowidth=(options.outWidth)/i; 12 //赋值缩放比例 13 options.inSampleSize=ratiowidth; 14 //设置显示的图片格式 15 options.inPreferredConfig=Config.RGB_565; 16 //设置为读取内容, 17 options.inJustDecodeBounds=false; 18 //得到缩略图 19 return BitmapFactory.decodeFile(filePath2, options); 20 }
当然现在有很多的第三方框架可以快速的实现这个功能,如Picasso等,其用法只是调用一下方法就可以了,相当对来说更容易(不会的朋友,可以在网上搜一下,很简单实 用的框架)。
2、其次就是采用三层缓存架构,提高图片的访问速度。三层缓存架构是内存-文件-网络。
内存是访问速度最快的部分但是分配的空间有限,所以不可能占用太多。其中内存缓存可以采用LRU算法(最近最少使用算法),来确定要删除内存中的那些图片,保存那 些图片。
文件就是将图片保存到本地,可以使SD卡中,也可以是手机内部存储中。
网络就是访问网络下载图片,进行图片的加载。
3、常见的png,JPG,webp等格式的图片在设置到UI上之前需要经过解码过程,而图片采用不同的码率,也会造成对内存的占用不同。下面介绍几种常见的解码率:
1)ALPHA_8格式的解码率,此时图片只有alpha值,没有RGB值,一个像素占用一个字节,内存占用是最小的,但是也是最不清晰的一种,极易照成画面失真,不建议使 用。
2)ARGB_4444 格式的解码率,这种格式的图片,看起来质量太差,已经不推荐使用。 而强烈推荐使用ARGB_8888来代替。一个像素占用2个字节,alpha(A) 值,Red(R)值,Green(G)值,Blue(B)值各占4个bites 。 共16bites,即2个字节
3)ARGB_8888 格式的解码率,一个像素占用4个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8个bites , 共32bites , 即4个字节。这是一种高 质量的图片格式,电脑上普通采用的格式。它也是Android手机上一个BitMap的默认格式。
4)RGB_565格式的解码率,一个像素占用2个字节,没有alpha(A)值,即不支持透明和半透明, Red(R)值占5个bites ,Green(G)值占6个bites ,Blue(B)值占5 个bites,共16bites,即2个字节。 对于半透明颜色的图片来说,该格式的图片能够达到比较好的呈现效果,相对于ARGB_8888来说也能减少一半的内存开销,因此它是一 个不错的选择。
总的来说,比较推荐用最后一种,性能较好,且没有alpha值,系统不用进行二次的渲染,可以很大的提高效率和性能。
4、最后一点,也是图片优化最重要的一点。重用Bitmap.
我们都知道bitmap会占用大量的内存空间,如下图:
所以可以重用已存在的bitmap内存区域。通过inBitmap属性可以使提升Bitmap循环效率。内存使用如下图:
使用这个属性,可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的bitmap会尝试去使用之前那张bitmap在heap中所占据的pixel data内存区域,而不是去问内存 重新申请一块区域来存放bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数 量的内存大小。
代码:
//得到选项 BitmapFactory.Options options=new BitmapFactory.Options(); options.inBitmap=mCurrentBitmap; mCurrentBitmap=BitmapFactory.decodeFile(filename,options);
使用这个属性需要注意一下几个限制条件:
1、在SDK 11 -> 18之间,重用的bitmap大小必须是一致的,例如给inBitmap赋值的图片大小为100-100,那么新申请的bitmap必须也为 100-100才能够被重用。从 SDK 19开始,新申请的bitmap大小必须小于或者等于已经赋值过的bitmap大小。
2、新申请的bitmap与旧的bitmap必须有相同的解码格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444与565格式的bitmap了。