您的位置:首页 > 其它

针对图片性能优化的总结

2011-09-18 03:14 246 查看
由于android设备的RAM较小,且Java的GC机制不够智能,经常会出现Out of memory异常。 当然,除了上面的原因,也有可能就是因为写的程序有bug,产生内存溢出。在进行图片较多的软件处理时,很有可能会遇到OOM(out of memory)的异常。

图片是一个非常消耗内存的资源,针对图片的处理需要进行特殊的处理。经过一段时间的调研,我总结出来几个注意事项。

尽量使用9png格式的图片

加载图片时,压缩图片后加载

尽快的手动标记回收图片资源

设置dalivk虚拟机的初始堆内存大小和GC效率(适用于不单单是图片的问题)

调用system.gc来执行垃圾回收(不赞成的方法)

下面是对这几个内容的仔细分析:

尽量使用9png格式的图片

    android系统为了提高图片的质量,提高android对各种屏幕的适应能力。系统推出了对.9.png格式图片的支持。这就就可以把一些图片在美工那里就做的非常小,之后还满足了产品对品质的要求。

加载图片时,图片压缩后加载

    正常程序中加载图片调用函数:BitmapFactory.decodeFile(imageFile);
    为了在加载图片时可以对图片压缩后在加载,对前面的这段代码进行一下加工:

1
BitmapFactory.Options opts =
new
BitmapFactory.Options();
2
opts.inJustDecodeBounds =
true
;
3
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);
    设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

    查看Android源码,Android提供了一种动态计算的方法。

01
public
static
int
computeSampleSize(BitmapFactory.Options options,
02
 
int
minSideLength,
int
maxNumOfPixels) {
03
 
int
initialSize = computeInitialSampleSize(options, minSideLength,
04
 
maxNumOfPixels);
05
06
 
int
roundedSize;
07
 
if
(initialSize <=
8
) {
08
 
roundedSize =
1
;
09
 
while
(roundedSize < initialSize) {
10
 
roundedSize <<=
1
;
11
 
}
12
 
}
else
{
13
 
roundedSize =(initialSize + 
7
) /
8
*
8
;
14
 
}
15
16
 
return
roundedSize;
17
}
18
19
private
static
int
computeInitialSampleSize(BitmapFactory.Options options,
20
 
int
minSideLength,
int
maxNumOfPixels) {
21
 
double
w = options.outWidth;
22
 
double
h = options.outHeight;
23
24
 
int
lowerBound = (maxNumOfPixels == -
1
) ?
1
:
25
 
(
int
) Math.ceil(Math.sqrt(w *h / maxNumOfPixels));
26
 
int
upperBound = (minSideLength == -
1
) ?
128
:
27
 
(
int
) Math.min(Math.floor(w / minSideLength),
28
 
Math.floor(h / minSideLength));
29
30
 
if
(upperBound < lowerBound) {
31
 
// return the larger one when there is no overlapping zone.
32
 
return
lowerBound;
33
 
}
34
35
 
if
((maxNumOfPixels == -
1
) &&
36
 
(minSideLength == -
1
)) {
37
 
return
1
;
38
 
}
else
if
(minSideLength == -
1
) {
39
 
return
lowerBound;
40
 
}
else
{
41
 
return
upperBound;
42
 
}
43
}
     使用该算法,就可动态计算出图片的inSampleSize。然后去设置好inSampleSize后才去加载图片。

          //解决加载图片 内存溢出的问题
//Options 只保存图片尺寸大小,不保存图片到内存
BitmapFactory.Options opts =new BitmapFactory.Options();
//缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数,SDK中建议其值是2的指数值,值越大会导致图片不清晰
opts.inSampleSize = 4;
Bitmap bmp = null;
bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);


  

尽快的手动标记回收图片资源

    在图片资源用完时,尽量手动的去标记一下这些已经用完的图片。帮助GC去识别不用的图片,并回收。
  

if(bitmapObject.isRecycled()==false) //如果没有回收
bitmapObject.recycle();


  

设置dalivk虚拟机的初始堆内存大小和GC效率(适用于不单单是图片的问题)

    对于Android平台来说,其托管层使用的Dalvik Java VM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体 原理我们可以参考开源工程,这里我们仅说下使用方法: private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。

  对于一些Android项目,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对 性能的影响十分敏感,除了 优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:

private final static int CWJ_HEAP_SIZE = 6*1024*1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理


调用system.gc来执行垃圾回收(不赞成的方法)

    在以上功能均不能满足条件时,考虑使用该方法。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: