每当我在onCreate
中强制进行肖像模式时setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
我收到错误
纵向模式与图像比例上的OOM VM预算有什么关系?
private void scaleFrom(BmpWrap image, Bitmap bmp)
{
if (image.bmp != null && image.bmp != bmp) {
image.bmp.recycle();
}
if (mDisplayScale > 0.99999 && mDisplayScale < 1.00001) {
image.bmp = bmp;
return;
}
int dstWidth = (int)(bmp.getWidth() * mDisplayScale);
int dstHeight = (int)(bmp.getHeight() * mDisplayScale);
image.bmp = Bitmap.createScaledBitmap(bmp, dstWidth, dstHeight, true);
}
private void resizeBitmaps()
{
scaleFrom(mBackground, mBackgroundOrig);
for (int i = 0; i < mBOrig.length; i++) {
scaleFrom(mB[i], mBOrig[i]);
}
for (int i = 0; i < mBlind.length; i++) {
scaleFrom(mBlind[i], mBlindOrig[i]);
}
for (int i = 0; i < mFrozen.length; i++) {
scaleFrom(mFrozen[i], mFrozenOrig[i]);
}
for (int i = 0; i < mTargeted.length; i++) {
scaleFrom(mTargeted[i], mTargetedOrig[i]);
}
scaleFrom(mBlink, mBlinkOrig);
scaleFrom(mWon, mWonOrig);
scaleFrom(mLost, mLostOrig);
mImagesReady = true;
}
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:498)
at android.graphics.Bitmap.createBitmap(Bitmap.java:465)
at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:370)
at com.company.app.View$hread.scaleFrom(View.java:313)
at com.company.app.View$hread.resizeBitmaps(View.java:337)
at com.company.app.View$hread.setSurfaceSize(View.java:480)
at com.company.app.View.surfaceChanged(View.java:905)
at android.view.SurfaceView.updateWindow(SurfaceView.java:538)
at android.view.SurfaceView.dispatchDraw(SurfaceView.java:339)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
at android.view.View.draw(View.java:6745)
at android.widget.FrameLayout.draw(FrameLayout.java:352)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1891)
at android.view.ViewRoot.draw(ViewRoot.java:1416)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1172)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1736)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:0)
每当您进行方向更改时,除静态属性外,应用程序将完全重新加载。 (请在此处阅读:http://developer.android.com/reference/android/app/Activity.html)
这意味着将重新加载您分配的所有位图(如果它们不是静态的)。 由于一个应用程序允许的内存为16 MB(我听到的某些设备上有24个),并且该位图作为原始位图(读取未压缩)存储在内存中,因此会导致内存使用量增加,从而导致OOM
除此之外,用于位图的内存是在堆内存之外分配的事实,但计算为部分内存,以便即使使用ddms或MAT也无法实际跟踪该问题。
请务必在onDestroy方法中回收所有位图,以便对它们进行垃圾回收。
最终让我脱离这一行的一件事是这三行代码(黑客):
System.gc();
System.runFinalization();
System.gc();
请注意,它会影响性能(大约500到750毫秒),因此它不适合有FPS关注的游戏,但对于应用来说它是完全合理的。
将它们放在createScaledBitmap调用的最开头。
它对我有用
修改:
根据您对相关位图所做的操作,您可以要求android打开它,以减少内存。我在处理这个问题时编写了这个函数。它试图尽可能大地打开位图:
private Bitmap getDownsampledBitmapFromFile(String fileName, int sampleSize) {
//Try to free up some memory
System.gc();
System.runFinalization();
System.gc();
BitmapFactory.Options options=new BitmapFactory.Options();//reset object
byte[] tempBuffer=new byte[8000];
options.inTempStorage = tempBuffer;
options.inSampleSize=sampleSize;
Bitmap downsampledBitmap = null;
try {
downsampledBitmap = BitmapFactory.decodeFile(fileNameToUpload, options);
} catch (OutOfMemoryError e) {
sampleSize ++;
}
return(downsampledBitmap);
}
答案 1 :(得分:0)
OOM异常是因为您通过在方向更改上重新创建位图来耗尽本机堆。有关背景,请参阅BitmapFactory OOM driving me nuts上的帖子。
解决这个问题的一种方法是(如Yahel所说)在onDestroy中回收你的位图。虽然位图数据在Native堆中,但我们发现下面的表单代码(在onDestroy中)在获取堆时更有效。
mBitmap.recycle();
mBitmap = null;