Android图片内存优化的几点心得

Android图片内存优化的几点心得


Admin
2012年6月24日
名人名言:时间就是生命,时间就是速度,时间就是力量。——郭沫若 

一、将图片转化为缩略图再加载: java



1 BitmapFactory.Options options = new BitmapFactory.Options();

2 options.inSampleSize = 2;

3 Bitmap img = BitmapFactory.decodeFile("/sdcard/1.png", options);


该段代码即是读取1.png的缩略图,长度、宽度都只有原图片的1/2。图片大小削减,占用的内存自然也变小了。这么作的弊病是图片质量变差,inSampleSize的值越大,图片的质量就越差。由于各手机厂商缩放图片的算法不合,在不合手机上的缩放图片质量可能会不合。笔者就遭受过moto手机上图片缩放后质量能够接管,三星手机上一样的缩放比例,质量却差不少的景象。 算法


 


二、用ARBG_4444色彩模式加载图片: 数组


Android中有四种,分别是: 函数


ALPHA_8:每一个像素占用1byte内存 post


ARGB_4444:每一个像素占用2byte内存 优化


ARGB_8888:每一个像素占用4byte内存 spa


RGB_565:每一个像素占用2byte内存 线程


Android默认的色彩模式为ARGB_8888,这个色彩模式色彩最细腻,显示质量最高。但一样的,占用的内存也最大。 code



1 BitmapFactory.Options options = new BitmapFactory.Options();

2 options.inPreferredConfig = Bitmap.Config.ARGB_4444;    

3 Bitmap img = BitmapFactory.decodeFile("/sdcard/1.png", options);


以上代码即是将1.png以ARGB_4444模式读出。内存削减当然不如第一种办法明显,然则对于大多半图片,看不出与ARGB_8888模式有什么差异。不过在读取有渐变结果的图片时,可能有色彩条呈现。别的,会影响图片的殊效处理惩罚。 对象


 


三、调用图片的recycle()办法:


这个其实不是真正降落图片内存的办法。首要目标是标识表记标帜图片对象,便利收受接管图片对象的本地数据。图片对象的本地数据占用的内存最大,而且与法度Java项目组的内存是分隔策画的。因此常常呈现Java heap足够应用,而图片产生OutOfMemoryError的景象。在图片不该用时调用该办法,能够有效降落图片本地数据的峰值,从而削减OutOfMemoryError的几率。不过调用了recycle()的图片对象处于“放弃”情况,调用时会形成法度错误。因此在没法包管该图片对象绝对不会被再次调用的景象下,不建议应用该办法。希罕要重视已经用setImageBitmap(Bitmap img)办法分派给控件的图片对象,可能会被体系类库调用,形成法度错误。


 


四、应用Matrix对象放大的图片如何更改色彩模式:


当然应用Matrix对象放大图片,必然会花费更多的内存,但有时辰也不得不如许作。放大后的图片应用的ARGB_8888色彩模式,就算原图片是ARGB_4444色彩模式也同样,而且没有办法在放大时直接指定色彩模式。能够采起如下办法更改图片色彩模式。



Matrix matrix = new Matrix();

float newWidth = 200;//图片放大后的宽度

float newHeight = 300;//图片放大后的长度

matrix.postScale(newWidth / img.getWidth(), newHeight/ img.getHeight());

Bitmap img1 = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);//得到放大的图片

img2 = img1.copy(Bitmap.Config.ARGB_4444, false);//得到ARGB_4444色彩模式的图片

img = null;

img1 = null;


这里比起原本的图片额外生成了一个图片对象img1。然则体系会主动收受接管img1,因此实际内存仍是削减了。


 


归结起来仍是以缩略图模式读取图片和削减图片中每一个像素占用的内存。这两种办法当然有效,然则也有各自的弊病。实际开辟中仍是应当按照景象酌情应用。最王道的办法,仍是避免垃圾对象的产生。例如在ListView的应用中,复用convertView等。如果应用AsyncTask加载图片,要及时将引用的ImageView对象置为null。由于AsyncTask是用线程池实现的,因此此中引用的对象可能会拥有很长的生命周期,形成GC没法开释。我仍是信赖Android的内存收受接管机制的,recycle什么的当然必然程度上有效,但总感受不合适Java内存收受接管的原则。(最后这句美尽是着魔了)

补充...

尽可能不要使用setImageBitmap或setImageResource
  或BitmapFactory.decodeResource来设置一张大图,
  由于这些函数在完成decode后,最终都是经过java层的createBitmap来完成的,
  须要消耗更多内存.
  所以,改用先经过BitmapFactory.decodeStream方法,
  建立出一个bitmap,再将其设为ImageView的 source,
  decodeStream最大的秘密在于其直接调用 JNI >> nativeDecodeAsset() 来完成decode,
  无需再使用java层的createBitmap,从而节省了java层的空间.
  若是在读取时加上图片的Config参数,能够更有效减小加载的内存,
  从而有效阻止抛出out of Memory异常
  另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各类分辨率来自动适应,
  使用了decodeStream以后,须要在hdpi和mdpi,ldpi中配置相应的图片资源,
  不然在不一样分辨率机器上都是一样大小(像素点数量),显示出来的大小就不对了.
  BitmapFactory.Options.inPreferredConfig
  ALPHA_8:数字为8,图形参数应该由一个字节来表示,应该是一种8位的位图
  ARGB_4444:4+4+4+4=16,图形的参数应该由两个字节来表示,应该是一种16位的位图.
  ARGB_8888:8+8+8+8=32,图形的参数应该由四个字节来表示,应该是一种32位的位图.
  RGB_565:5+6+5=16,图形的参数应该由两个字节来表示,应该是一种16位的位图.
  ALPHA_8,ARGB_4444,ARGB_8888都是透明的位图,也就是所字母A表明透明.
  ARGB_4444:意味着有四个参数,即A,R,G,B,每个参数由4bit表示.
  ARGB_8888:意味着有四个参数,即A,R,G,B,每个参数由8bit来表示.
  RGB_565:意味着有三个参数,R,G,B,三个参数分别占5bit,6bit,5bit.
  BitmapFactory.Options.inPurgeable;
  若是 inPurgeable 设为True的话表示使用BitmapFactory建立的Bitmap
  用于存储Pixel的内存空间系统内存不足时能够被回收,
  在应用须要再次访问Bitmap的Pixel时(如绘制Bitmap或是调用getPixel),
  系统会再次调用BitmapFactory decoder从新生成Bitmap的Pixel数组.
  为了可以从新解码图像,bitmap要可以访问存储Bitmap的原始数据.
  在inPurgeable为false时表示建立的Bitmap的Pixel内存空间不能被回收,
  这样BitmapFactory在不停decodeByteArray建立新的Bitmap对象,
  不一样设备的内存不一样,所以可以同时建立的Bitmap个数可能有所不一样,
  200个bitmap足以使大部分的设备从新OutOfMemory错误.
  当isPurgable设为true时,系统中内存不足时,
  能够回收部分Bitmap占据的内存空间,这时通常不会出现OutOfMemory 错误.

相关文章
相关标签/搜索