Android内存优化之图片优化的方法

一般来说,图片是APP占用内存高的主要原因,所以优化图片的内存占用是避免OOM的根本手段。对于图片占用的内存,我们可能总有这样的误区:图片本身所占的存储空间越小,占用的内存越小。所以认为只要将图片进行压缩,就相当于减小了内存占用。其实这是不对的,图片占用的存储空间大小与所占内存大小没有直接关系。本篇文章将为大家分享Android内存优化之图片优化的方法,以作参考。

4240d08fba998218f6f7ed350c7db892.jpeg

1. 对图片本身进行操作

尽量不要使用setImageBitmap、setImageResource、 BitmapFactory.decodeResource来建立一个大图,因为这些方法最终都是通过 Java 层的 createBitmap 来完成的,需要消耗更多内存。

因此,请改为先通过BitmapFactory.DecodeStream方法,创建一个 bitmap,然后将其设置为ImageView的source、decodeStream最大的秘密就是直接调用JNInativeDecodeAssett() 来完成 decode,无需再使用 Java 层的 createBitmap,从而节省了 Java 层的空间。

如果在读取时加入图片的Config参数,可以更有效地减少加载的内存,从而更有效地防止内存异常的抛出。另外decodeStream直接拍照读取字节码,不会根据机器的各种分辨率自动适配使用decodeStream后,需要在hdpimdpildpi中配置相应的图片资源,否则在不同分辨率的机器上都会是同样的大小(像素点数量),显示的尺寸错误。

代码如下:


InputStream is = this.getResources().openRawResource(R.drawable.pic);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
Bitmap btp =BitmapFactory.decodeStream(is,null,options);

以上代码即是读取 drawable 下名为 pic 图片的缩略图,长度、宽度都只有原图片的 1/2。图片大小减少,占用的内存自然也变小了。这么做的弊端是图片质量变差,inSampleSize 的值越大,图片的质量就越差。由于各手机厂商缩放图片的算法不同,在不同手机上的缩放图片质量可能会不同。

2. 调用图片的 recycle() 方法

复制代码代码如下:

if(!bmp.isRecycle() ){
   bmp.recycle()    //回收图片所占的内存
   system.gc()      //提醒系统及时回收
}

这种方法其实不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。

图片对象的本地数据占用的内存最大,而且与程序 Java 部分的内存是分开计算的。所以经常出现 Java heap 足够使用,而图片发生 OutOfMemoryError 的情况。

在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少 OutOfMemoryError 的概率。不过调用了 recycle() 的图片对象处于“废弃”状态,调用时会造成程序错误。

所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。特别要注意已经用 setImageBitmap(Bitmapimg) 方法分配给控件的图片对象,可能会被系统类库调用,造成程序错误。

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 内存收受接管的原则。

以上就是Android内存优化之图片优化的方法的详细内容,更多关于Android性能优化之内存优化的知识点,可以关注小编!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容