2. 调用图片的 recycle() 方法
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)代码如下:
if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
这种方法其实不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。图片对象的本地数据占用的内存最大,而且与程序 Java 部分的内存是分开计算的。所以经常出现 Java heap 足够使用,而图片发生 OutOfMemoryError 的情况。在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少 OutOfMemoryError 的概率。不过调用了 recycle() 的图片对象处于“废弃”状态,调用时会造成程序错误。所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。特别要注意已经用 setImageBitmap(Bitmap
img) 方法分配给控件的图片对象,可能会被系统类库调用,造成程序错误。
3. 以最省内存的方式读取本地资源的图片
代码如下:
/**
* 以最省内存的方式读取本地资源的图片
*/
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is,null,opt);
}
Android 中加载图片的颜色模式有四种,分别是:ALPHA_8:每个像素占用 1byte 内存、ARGB_4444:每个像素占用 2byte 内存、ARGB_8888:每个像素占用 4byte 内存、RGB_565:每个像素占用 2byte 内存。Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。以上代码即是将图片资源以 RGB_565 (或以 ARGB_4444)模式读出。内存减少虽然不如第一种方法明显,但是对于大多数图片,看不出与 ARGB_8888 模式有什么差别。不过在读取有渐变效果的图片时,可能有颜色条出现。另外,会影响图片的特效处理。
4. 使用 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 内存收受接管的原则。