在Android应用程序开发当中,最常见的内存溢出问题(OOM)是在加载图片时出现的,尤其是在不知道图片大小的情况下。
一、图片加载时潜在的内存溢出操作主要包括以下两种情况:
- 1. 从网络上获取图片,直到下载图片的时候,我们才知道图片的大小。因此在开发的时候,有不确定性。
- 2. 从相册或者手机拍摄图片,因为现在的手机摄像头的分辨率可能会很高,在加载的时候需要对图片进行处理,才能进行使用。
值得注意的是,虽然我们的手机可以配置很大的内存空间,可以android系统是通过全局来分配图片内存空间的,这就意味着,即使有很大的内在空间,内存溢出问题(OOP)也依然存在,因为所有的应用都要共享同一个图片内存池。(通过BitmapFactory来进行解析)
二、解决办法
我们想通过降低图片质量的方式,来压缩图片大小,因为我们的ImageView显示的大小是确定的,不论原始图片是多大的图片,最终也只能显示所见的大小,但是消耗的内存却不相同,因此我们通过缩小预加载图片的大小,来降低内存的损耗,防止出现OOP。
如下边这段代码:
private static Bitmap getResizedImage(String path, byte[] data, int targetWidth){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int width = options.outWidth;
int ssize = sampleSize(width, targetWidth);
options = new BitmapFactory.Options();
options.inSampleSize = ssize;
Bitmap bm = null;
try{
bm = decode(path, data, options);
}catch(OutOfMemoryError e){
AQUtility.report(e);
}
return bm;
}
private static int sampleSize(int width, int target){
int result = 1;
for(int i = 0; i < 10; i++){
if(width < target * 2){
break;
}
width = width / 2;
result = result * 2;
}
return result;
}
同时我们另一种更方便的解决办法,就是引入Aquery组件,使问题变的更加简单。
从网络下载图片时:
String url = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_b.jpg";
aq.id(R.id.image1).image(imageUrl, true, true, 200, 0);
加载本地图片时:
File file = new File(path);
//假设我们要需要等比压缩到宽度为300像素
aq.id(R.id.avatar).image(file, 300);
原文地址:http://blog.androidquery.com/2011/05/down-sample-images-to-avoid-out-of.html
android-query资料地址:http://code.google.com/p/android-query/