Принудительный портретный режим изменения размера растрового изображения OOM - PullRequest
0 голосов
/ 26 января 2011

Всякий раз, когда я включаю портретный режим в onCreate

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

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

Какое отношение имеет портретный режим к бюджету виртуальной машины OOM в масштабе изображения?

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)

Ответы [ 2 ]

0 голосов
/ 31 марта 2011

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

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

mBitmap.recycle();
mBitmap = null;
0 голосов
/ 26 января 2011

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

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

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

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

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

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

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

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

Это сработало для меня

Редактировать:

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

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

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...