欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android内存优化之图片优化

程序员文章站 2023-12-04 11:24:34
对图片本身进行操作。尽量不要使用setimagebitmap、setimageresource、bitmapfactory.decoderesource来设置一张大图,因为...

对图片本身进行操作。尽量不要使用setimagebitmap、setimageresource、bitmapfactory.decoderesource来设置一张大图,因为这些方法在完成decode后,最终都是通过java层的createbitmap来完成的,需要消耗更多内存。因此,改用先通过bitmapfactory.decodestream方法,创建出一个bitmap,再将其设为imageview的source,decodestream最大的秘密在于其直接调用jni>>nativedecodeasset()来完成decode,无需再使用java层的createbitmap,从而节省了java层的空间。如果在读取时加上图片的config参数,可以更有效的减少加载的内存,从而更有效阻止抛出内存异常。另外,decodestream直接拿图片来读取字节码了,不会根据机器的各种分辨率来自动适应,使用了decodestream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

复制代码 代码如下:

inputstreamis=this.getresources().openrawresource(r.drawable.pic1);
bitmapfactory.optionsoptions=newbitmapfactory.options();
options.injustdecodebounds=false;
options.insamplesize=10;//width,hight设为原来的十分一
bitmapbtp=bitmapfactory.decodestream(is,null,options);

复制代码 代码如下:

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

复制代码 代码如下:

/**
*以最省内存的方式读取本地资源的图片
*@paramcontext
*@paramresid
*@return
*/
publicstaticbitmapreadbitmap(contextcontext,intresid){
bitmapfactory.optionsopt=newbitmapfactory.options();
opt.inpreferredconfig=bitmap.config.rgb_565;
opt.inpurgeable=true;
opt.ininputshareable=true;
//获取资源图片
inputstreamis=context.getresources().openrawresource(resid);
returnbitmapfactory.decodestream(is,null,opt);
}

option中的值指的是,图片进行缩放的比例,sdk中建议其值是2的指数值,值越大会导致图片不清晰。长度、宽度都只有原图片的1/2。图片大小减少,占用的内存自然也变小了。这么做的弊端是图片质量变差,insamplesize的值越大,图片的质量就越差。由于各手机厂商缩放图片的算法不同,在不同手机上的缩放图片质量可能会不同。笔者就遭遇过moto手机上图片缩放后质量可以接受,三星手机上同样的缩放比例,质量却差很多的情况。

android中有四种,分别是
alpha_8:每个像素占用1byte内存
argb_4444:每个像素占用2byte内存
argb_8888:每个像素占用4byte内存
rgb_565:每个像素占用2byte内存
android默认的颜色模式为argb_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。
以上代码即是将1.png以argb_4444模式读出。内存减少虽然不如第一种方法明显,但是对于大多数图片,看不出与argb_8888模式有什么差别。不过在读取有渐变效果的图片时,可能有颜色条出现。另外,会影响图片的特效处理。
优化dalvik虚拟机的堆内存分配。对于android平台来说,其托管层使用的dalvikjavavm从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉gc处理,使用dalvik.system.vmruntime类提供的settargetheaputilization方法可以增强程序堆内存的处理效率。使用方法:
复制代码 代码如下:

privatefinalstaticfloattarget_heap_utilization=0.75f;
vmruntime.getruntime().settargetheaputilization(target_heap_utilization);

即可。
还有就是可以定义堆内存的大小。
复制代码 代码如下:

privatefinalstaticintcwj_heap_size=6*1024*1024;vmruntime.getruntime().setminimumheapsize(cwj_heap_size);//设置最小heap内存为6mb大小

调用图片的recycle()方法:
这个其实不是真正降低图片内存的方法。主要目的是标记图片对象,方便回收图片对象的本地数据。图片对象的本地数据占用的内存最大,而且与程序java部分的内存是分开计算的。所以经常出现javaheap足够使用,而图片发生outofmemoryerror的情况。在图片不使用时调用该方法,可以有效降低图片本地数据的峰值,从而减少outofmemoryerror的概率。不过调用了recycle()的图片对象处于“废弃”状态,调用时会造成程序错误。所以在无法保证该图片对象绝对不会被再次调用的情况下,不建议使用该方法。特别要注意已经用setimagebitmap(bitmapimg)方法分配给控件的图片对象,可能会被系统类库调用,造成程序错误。

使用matrix对象放大的图片如何更改颜色模式
虽然使用matrix对象放大图片,必定会耗费更多的内存,但有时候也不得不这样做。放大后的图片使用的argb_8888颜色模式,就算原图片是argb_4444颜色模式也一样,而且没有办法在放大时直接指定颜色模式。可以采用以下办法更改图片颜色模式。
代码如下
复制代码 代码如下:

matrixmatrix=newmatrix();
floatnewwidth=200;//图片放大后的宽度
floatnewheight=300;//图片放大后的长度
matrix.postscale(newwidth/img.getwidth(),newheight/img.getheight());
bitmapimg1=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,所以实际内存还是减少了。