java.lang.OutOfMemoryError
atandroid.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
atandroid.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
atandroid.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
这是一个内存溢出的错误,总感觉项目的apk文件并不大,怎么会出现内存以溢出。
通常是因为加载分辨率比较大的图片,图片的本身大小不一定大。
图片的分辨率比较大,例如大小为300KB,分辨率为1280*1920的一张图片,300KB其实并不算大,但是android在加载图片时并不是看图片真实大小大小,而是看图片的分辨率,在实际加载时android认为该图片大小为9MB,在这我并没有胡说,在android中每一种颜色的每一个像素点为1字节,1280*1920/1024=2400KB位图图片是RGB三色,在Android则是ARGB,A为透明度,RGB就不多说了。2400*4/1024=9.375MB,也就是说该图片在加载时占用了9MB的内存。一张就是9MB,多加载几张,再加上其他内容,可想而知,这个app的所占运行不就很大了。
仔细算下来也不过几十兆,现在手机的RAM至少512MB了,区区几十兆算的了什么,这也不可能产生内存溢出。其实在android中,这些运存并不是让应用程序随意使用的,android对每一个进程所占用的运存是有上限的,即heap是有上限的。如果手机或模拟器的heap比较大,java.lang.OutOfMemoryError这个运行时期的异常出现的就比较少,但无论heap有多大,一个手机的heap是固定的。G1:16MB,Droid:24MB,Nexus One:32MB,Xoom:48MB等。
现在已经明白java.lang.OutOfMemoryError出现的原因了
那么如何解决?
解决方法也很简单就是图片缩放显示。
//获取屏幕大小
WindowManager manager = getWindowManager();
Point point = new Point();
manager.getDefaultDisplay().getSize(point);
mScreenWidth = point.x;
mScreenHight = point.y;
BitmapFactory.Options options = new Options();
// 不解析图片
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),mImages[0], options);
int imgWidth = options.outWidth;
int imgHeigth = options.outHeight;
int scaleWidth = imgWidth / mScreenWidth;
int scaleHeight = imgHeigth / mScreenHight;
int scale = scaleWidth > scaleHeight ? scaleWidth : scaleHeight;
ActivityManager am =(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int memory = am.getMemoryClass();
if (memory < 32)
scale = scale > 2 ? scale : 2;
options.inSampleSize = scale;
for (int i = 0; i < mImages.length; i++) {
ImageView imageView = new ImageView(GuideActivity.this);
// 解析图片
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
mImages[i], options);
imageView.setImageBitmap(bitmap);
mList.add(imageView);
}
至于如何获取heap的大小也很简单:
ActivityManageram=(ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int memorySize = am.getMemoryClass();
当memorySize比较小时在缩放图片,可保持图片的清晰度,但会增加响应时间。