2011-01-25 4 views
0

Всякий раз, когда я заставляю портретный режим в OnCreateПринуждение портретный режим ООМ растрового размера

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

Я получаю ошибку

Что портретный режим должен делать с бюджетом ООГО 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

Всякий раз, когда вы делаете изменение ориентации, приложение перезагружается полностью, за исключением статических свойств. (читайте здесь: http://developer.android.com/reference/android/app/Activity.html)

Это означает, что все растровые изображения, которые вы выделили, если они не были статичными, будут перезагружены. Поскольку память, разрешенная для одного приложения, составляет 16 МБ (24 на некоторых устройствах, которые я слышу), и это растровое изображение хранится в памяти как необработанное растровое изображение (чтение не сжато), это создает всплеск в использовании памяти, который может привести к OOM

Добавьте к этому тот факт, что память, используемая для растровых изображений, выделяется вне вашей памяти кучи, но считается как часть ее, так что вы не можете действительно трассировать эту проблему, даже используя ddms или MAT.

Обязательно переработайте все ваши растровые изображения в вашем методе onDestroy, чтобы они могли собирать мусор.

Единственное, что, наконец, вытащил меня из этого одного эти три строки кода (Hack):

System.gc(); 
System.runFinalization(); 
System.gc(); 

Остерегайтесь, хотя, это влияет на производительность (около 500 до 750 мс), поэтому он не подходит для игры с концерном FPS, но для приложения это вполне разумно.

Поместите их в самом начале вызова createScaledBitmap.

Он работал для меня

Edit:

В зависимости от того, что вы делаете с растровым в вопрос вы можете задать андроида, чтобы открыть субдискретизации, принимая меньше памяти. Я написал эту функцию при решении этой проблемы. Он пытается открыть растровое изображение как большое, насколько это возможно:

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); 

    } 
+0

Вы имеете на это следующие значения: – user583739

+0

System.gc(); System.runFinalization(); System.gc(); image.bmp = Bitmap.createScaledBitmap (bmp, dstWidth, dstHeight, true); – user583739

+0

К сожалению, эта же ошибка по-прежнему вызывает такую ​​же ошибку. – user583739

0

Исключения ООГО происходит потому, что вы работаете из родной кучи воссоздавая растровые изображения на изменении ориентации. Смотрите мой пост на BitmapFactory OOM driving me nuts для фона.

Один из способов обойти это (как говорит Яхель) переработать ваши растровые изображения в onDestroy. Хотя данные растрового изображения находятся в Нативной куче, и мы обнаружили, что код формы ниже (в onDestroy) более эффективен в получении кучи назад.

mBitmap.recycle(); 
mBitmap = null;