0

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

2 に答える 2

0

向きを変更すると、アプリは静的プロパティを除いて完全に再読み込みされます。(ここを読む: http://developer.android.com/reference/android/app/Activity.html )

これは、静的でない場合に割り当てたすべてのビットマップが再ロードされることを意味します。1 つのアプリに許可されているメモリは 16 MB (私が聞いた一部のデバイスでは 24) であり、そのビットマップは生のビットマップ (圧縮されていない読み取り) としてメモリに格納されるため、OOM につながるメモリ使用量のスパイクが発生します。

それに加えて、ビットマップに使用されるメモリはヒープメモリの外側に割り当てられますが、その一部としてカウントされるため、ddms または MAT を使用しても実際にその問題を追跡することはできません。

onDestroy メソッドですべてのビットマップをリサイクルして、ガベージ コレクトできるようにしてください。

最終的にこの問題から抜け出したのは、次の 3 行のコード (ハック) です。

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

    }
于 2011-01-26T19:47:23.347 に答える
0

OOM の例外は、方向の変更時にビットマップを再作成することによってネイティブ ヒープが不足しているためです。背景については、 BitmapFactory OOMでの私の投稿を参照してください。

これを回避する 1 つの方法は、(Yahel が言うように) onDestroy でビットマップをリサイクルすることです。ビットマップ データはネイティブ ヒープにありますが、以下の形式のコード (onDestroy 内) の方がヒープを取り戻すのにより効果的であることがわかりました。

mBitmap.recycle();
mBitmap = null;
于 2011-03-30T22:41:36.987 に答える